Updated Boost libraries
This commit is contained in:
@@ -115,6 +115,12 @@ namespace boost { namespace accumulators
|
||||
{
|
||||
}
|
||||
|
||||
droppable_accumulator_base(droppable_accumulator_base const &that)
|
||||
: Accumulator(*static_cast<Accumulator const *>(&that))
|
||||
, ref_count_(that.ref_count_)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Args>
|
||||
void operator ()(Args const &args)
|
||||
{
|
||||
@@ -162,6 +168,11 @@ namespace boost { namespace accumulators
|
||||
: droppable_accumulator::base(args)
|
||||
{
|
||||
}
|
||||
|
||||
droppable_accumulator(droppable_accumulator const &that)
|
||||
: droppable_accumulator::base(*static_cast<typename droppable_accumulator::base const *>(&that))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/mpl/end.hpp>
|
||||
#include <boost/mpl/map.hpp>
|
||||
#include <boost/mpl/set.hpp>
|
||||
#include <boost/mpl/copy.hpp>
|
||||
#include <boost/mpl/fold.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/mpl/sort.hpp>
|
||||
@@ -26,6 +28,7 @@
|
||||
#include <boost/mpl/is_sequence.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/mpl/insert_range.hpp>
|
||||
#include <boost/mpl/back_inserter.hpp>
|
||||
#include <boost/mpl/transform_view.hpp>
|
||||
#include <boost/mpl/inherit_linearly.hpp>
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
@@ -94,15 +97,49 @@ namespace boost { namespace accumulators
|
||||
template<typename A, typename B>
|
||||
struct is_dependent_on
|
||||
: is_base_and_derived<
|
||||
typename undroppable<B>::type
|
||||
typename feature_of<typename undroppable<B>::type>::type
|
||||
, typename undroppable<A>::type
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename Feature>
|
||||
struct dependencies_of
|
||||
{
|
||||
typedef typename Feature::dependencies type;
|
||||
};
|
||||
|
||||
// Should use mpl::insert_range, but doesn't seem to work with mpl sets
|
||||
template<typename Set, typename Range>
|
||||
struct set_insert_range
|
||||
: mpl::fold<
|
||||
Range
|
||||
, Set
|
||||
, mpl::insert<mpl::_1, mpl::_2>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename Features>
|
||||
struct collect_abstract_features
|
||||
: mpl::fold<
|
||||
Features
|
||||
, mpl::set0<>
|
||||
, set_insert_range<
|
||||
mpl::insert<mpl::_1, feature_of<mpl::_2> >
|
||||
, collect_abstract_features<dependencies_of<mpl::_2> >
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename Features>
|
||||
struct depends_on_base
|
||||
: mpl::inherit_linearly<
|
||||
typename mpl::sort<Features, is_dependent_on<mpl::_1, mpl::_2> >::type
|
||||
typename mpl::sort<
|
||||
typename mpl::copy<
|
||||
typename collect_abstract_features<Features>::type
|
||||
, mpl::back_inserter<mpl::vector0<> >
|
||||
>::type
|
||||
, is_dependent_on<mpl::_1, mpl::_2>
|
||||
>::type
|
||||
// Don't inherit multiply from a feature
|
||||
, mpl::if_<
|
||||
is_dependent_on<mpl::_1, mpl::_2>
|
||||
@@ -319,7 +356,7 @@ namespace boost { namespace accumulators
|
||||
type;
|
||||
};
|
||||
|
||||
// BUGBUG work around a MPL bug wrt map insertion
|
||||
// BUGBUG work around an MPL bug wrt map insertion
|
||||
template<typename FeatureMap, typename Feature>
|
||||
struct insert_feature
|
||||
: mpl::eval_if<
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <boost/accumulators/statistics/peaks_over_threshold.hpp>
|
||||
#include <boost/accumulators/statistics/pot_tail_mean.hpp>
|
||||
#include <boost/accumulators/statistics/pot_quantile.hpp>
|
||||
#include <boost/accumulators/statistics/p_square_cumulative_distribution.hpp>
|
||||
#include <boost/accumulators/statistics/p_square_cumul_dist.hpp>
|
||||
#include <boost/accumulators/statistics/p_square_quantile.hpp>
|
||||
#include <boost/accumulators/statistics/skewness.hpp>
|
||||
#include <boost/accumulators/statistics/stats.hpp>
|
||||
@@ -45,7 +45,7 @@
|
||||
#include <boost/accumulators/statistics/weighted_median.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_moment.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_peaks_over_threshold.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_p_square_cumulative_distribution.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_p_square_quantile.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_skewness.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_sum.hpp>
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace impl
|
||||
}
|
||||
|
||||
// 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.
|
||||
// the minimum and maximum of the cached samples as well as under and overflow bins.
|
||||
// Store their lower bounds (bin_positions) and fill the bins with the cached samples (samples_in_bin).
|
||||
if (cnt == this->cache_size)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <boost/accumulators/statistics/count.hpp>
|
||||
#include <boost/accumulators/statistics/p_square_quantile.hpp>
|
||||
#include <boost/accumulators/statistics/density.hpp>
|
||||
#include <boost/accumulators/statistics/p_square_cumulative_distribution.hpp>
|
||||
#include <boost/accumulators/statistics/p_square_cumul_dist.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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_CUMUL_DIST_HPP_DE_01_01_2006
|
||||
#define BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMUL_DIST_HPP_DE_01_01_2006
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/accumulators/framework/accumulator_base.hpp>
|
||||
#include <boost/accumulators/framework/extractor.hpp>
|
||||
#include <boost/accumulators/numeric/functional.hpp>
|
||||
#include <boost/accumulators/framework/parameters/sample.hpp>
|
||||
#include <boost/accumulators/statistics_fwd.hpp>
|
||||
#include <boost/accumulators/statistics/count.hpp>
|
||||
|
||||
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<typename Sample>
|
||||
struct p_square_cumulative_distribution_impl
|
||||
: accumulator_base
|
||||
{
|
||||
typedef typename numeric::functional::average<Sample, std::size_t>::result_type float_type;
|
||||
typedef std::vector<float_type> array_type;
|
||||
typedef std::vector<std::pair<float_type, float_type> > histogram_type;
|
||||
// for boost::result_of
|
||||
typedef iterator_range<typename histogram_type::iterator> result_type;
|
||||
|
||||
template<typename Args>
|
||||
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<typename Args>
|
||||
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<short>(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<typename Args>
|
||||
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<count>
|
||||
, p_square_cumulative_distribution_num_cells
|
||||
{
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
typedef accumulators::impl::p_square_cumulative_distribution_impl<mpl::_1> impl;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// extract::p_square_cumulative_distribution
|
||||
//
|
||||
namespace extract
|
||||
{
|
||||
extractor<tag::p_square_cumulative_distribution> const p_square_cumulative_distribution = {};
|
||||
|
||||
BOOST_ACCUMULATORS_IGNORE_GLOBAL(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<tag::p_square_cumulative_distribution>
|
||||
{
|
||||
typedef tag::weighted_p_square_cumulative_distribution type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct feature_of<tag::weighted_p_square_cumulative_distribution>
|
||||
: feature_of<tag::p_square_cumulative_distribution>
|
||||
{
|
||||
};
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
||||
@@ -1,260 +1,19 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// p_square_cumulative_distribution.hpp
|
||||
//
|
||||
// Copyright 2005 Daniel Egloff, Olivier Gygi. Distributed under the Boost
|
||||
// Copyright 2012 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_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_DE_01_01_2006
|
||||
#define BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_DE_01_01_2006
|
||||
#ifndef BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012
|
||||
#define BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/accumulators/framework/accumulator_base.hpp>
|
||||
#include <boost/accumulators/framework/extractor.hpp>
|
||||
#include <boost/accumulators/numeric/functional.hpp>
|
||||
#include <boost/accumulators/framework/parameters/sample.hpp>
|
||||
#include <boost/accumulators/statistics_fwd.hpp>
|
||||
#include <boost/accumulators/statistics/count.hpp>
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
|
||||
# pragma message ("Warning: This header is deprecated. Please use: boost/accumulators/statistics/p_square_cumul_dist.hpp")
|
||||
#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
|
||||
# warning "This header is deprecated. Please use: boost/accumulators/statistics/p_square_cumul_dist.hpp"
|
||||
#endif
|
||||
|
||||
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<typename Sample>
|
||||
struct p_square_cumulative_distribution_impl
|
||||
: accumulator_base
|
||||
{
|
||||
typedef typename numeric::functional::average<Sample, std::size_t>::result_type float_type;
|
||||
typedef std::vector<float_type> array_type;
|
||||
typedef std::vector<std::pair<float_type, float_type> > histogram_type;
|
||||
// for boost::result_of
|
||||
typedef iterator_range<typename histogram_type::iterator> result_type;
|
||||
|
||||
template<typename Args>
|
||||
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<typename Args>
|
||||
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<short>(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<typename Args>
|
||||
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<count>
|
||||
, p_square_cumulative_distribution_num_cells
|
||||
{
|
||||
/// INTERNAL ONLY
|
||||
///
|
||||
typedef accumulators::impl::p_square_cumulative_distribution_impl<mpl::_1> impl;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// extract::p_square_cumulative_distribution
|
||||
//
|
||||
namespace extract
|
||||
{
|
||||
extractor<tag::p_square_cumulative_distribution> const p_square_cumulative_distribution = {};
|
||||
|
||||
BOOST_ACCUMULATORS_IGNORE_GLOBAL(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<tag::p_square_cumulative_distribution>
|
||||
{
|
||||
typedef tag::weighted_p_square_cumulative_distribution type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct feature_of<tag::weighted_p_square_cumulative_distribution>
|
||||
: feature_of<tag::p_square_cumulative_distribution>
|
||||
{
|
||||
};
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
#include <boost/accumulators/statistics/p_square_cumul_dist.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <boost/accumulators/statistics/median.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_p_square_quantile.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_density.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_p_square_cumulative_distribution.hpp>
|
||||
#include <boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp>
|
||||
|
||||
namespace boost { namespace accumulators
|
||||
{
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// weighted_p_square_cumul_dist.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_CUMUL_DIST_HPP_DE_01_01_2006
|
||||
#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMUL_DIST_HPP_DE_01_01_2006
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/accumulators/framework/accumulator_base.hpp>
|
||||
#include <boost/accumulators/framework/extractor.hpp>
|
||||
#include <boost/accumulators/numeric/functional.hpp>
|
||||
#include <boost/accumulators/framework/parameters/sample.hpp>
|
||||
#include <boost/accumulators/statistics_fwd.hpp>
|
||||
#include <boost/accumulators/statistics/count.hpp>
|
||||
#include <boost/accumulators/statistics/sum.hpp>
|
||||
#include <boost/accumulators/statistics/p_square_cumul_dist.hpp> // 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<typename Sample, typename Weight>
|
||||
struct weighted_p_square_cumulative_distribution_impl
|
||||
: accumulator_base
|
||||
{
|
||||
typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample;
|
||||
typedef typename numeric::functional::average<weighted_sample, std::size_t>::result_type float_type;
|
||||
typedef std::vector<std::pair<float_type, float_type> > histogram_type;
|
||||
typedef std::vector<float_type> array_type;
|
||||
// for boost::result_of
|
||||
typedef iterator_range<typename histogram_type::iterator> result_type;
|
||||
|
||||
template<typename Args>
|
||||
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<typename Args>
|
||||
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<short>(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<typename Args>
|
||||
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<count, sum_of_weights>
|
||||
, p_square_cumulative_distribution_num_cells
|
||||
{
|
||||
typedef accumulators::impl::weighted_p_square_cumulative_distribution_impl<mpl::_1, mpl::_2> impl;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// extract::weighted_p_square_cumulative_distribution
|
||||
//
|
||||
namespace extract
|
||||
{
|
||||
extractor<tag::weighted_p_square_cumulative_distribution> const weighted_p_square_cumulative_distribution = {};
|
||||
|
||||
BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_p_square_cumulative_distribution)
|
||||
}
|
||||
|
||||
using extract::weighted_p_square_cumulative_distribution;
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
|
||||
#endif
|
||||
@@ -1,262 +1,19 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// weighted_p_square_cumulative_distribution.hpp
|
||||
//
|
||||
// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost
|
||||
// Copyright 2012 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_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_DE_01_01_2006
|
||||
#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_DE_01_01_2006
|
||||
#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012
|
||||
#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <boost/parameter/keyword.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/accumulators/framework/accumulator_base.hpp>
|
||||
#include <boost/accumulators/framework/extractor.hpp>
|
||||
#include <boost/accumulators/numeric/functional.hpp>
|
||||
#include <boost/accumulators/framework/parameters/sample.hpp>
|
||||
#include <boost/accumulators/statistics_fwd.hpp>
|
||||
#include <boost/accumulators/statistics/count.hpp>
|
||||
#include <boost/accumulators/statistics/sum.hpp>
|
||||
#include <boost/accumulators/statistics/p_square_cumulative_distribution.hpp> // for named parameter p_square_cumulative_distribution_num_cells
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
|
||||
# pragma message ("Warning: This header is deprecated. Please use: boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp")
|
||||
#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
|
||||
# warning "This header is deprecated. Please use: boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp"
|
||||
#endif
|
||||
|
||||
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<typename Sample, typename Weight>
|
||||
struct weighted_p_square_cumulative_distribution_impl
|
||||
: accumulator_base
|
||||
{
|
||||
typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample;
|
||||
typedef typename numeric::functional::average<weighted_sample, std::size_t>::result_type float_type;
|
||||
typedef std::vector<std::pair<float_type, float_type> > histogram_type;
|
||||
typedef std::vector<float_type> array_type;
|
||||
// for boost::result_of
|
||||
typedef iterator_range<typename histogram_type::iterator> result_type;
|
||||
|
||||
template<typename Args>
|
||||
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<typename Args>
|
||||
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<short>(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<typename Args>
|
||||
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<count, sum_of_weights>
|
||||
, p_square_cumulative_distribution_num_cells
|
||||
{
|
||||
typedef accumulators::impl::weighted_p_square_cumulative_distribution_impl<mpl::_1, mpl::_2> impl;
|
||||
};
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// extract::weighted_p_square_cumulative_distribution
|
||||
//
|
||||
namespace extract
|
||||
{
|
||||
extractor<tag::weighted_p_square_cumulative_distribution> const weighted_p_square_cumulative_distribution = {};
|
||||
|
||||
BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_p_square_cumulative_distribution)
|
||||
}
|
||||
|
||||
using extract::weighted_p_square_cumulative_distribution;
|
||||
|
||||
}} // namespace boost::accumulators
|
||||
#include <boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <functional>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/range.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/placeholders.hpp>
|
||||
|
||||
175
project/jni/boost/include/boost/algorithm/clamp.hpp
Normal file
175
project/jni/boost/include/boost/algorithm/clamp.hpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2008-2012.
|
||||
|
||||
Distributed under the 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 June 2009 mtc First version
|
||||
23 Oct 2010 mtc Added predicate version
|
||||
|
||||
*/
|
||||
|
||||
/// \file clamp.hpp
|
||||
/// \brief Clamp algorithm
|
||||
/// \author Marshall Clow
|
||||
///
|
||||
/// Suggested by olafvdspek in https://svn.boost.org/trac/boost/ticket/3215
|
||||
|
||||
#ifndef BOOST_ALGORITHM_CLAMP_HPP
|
||||
#define BOOST_ALGORITHM_CLAMP_HPP
|
||||
|
||||
#include <functional> // For std::less
|
||||
#include <iterator> // For std::iterator_traits
|
||||
#include <cassert>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/mpl/identity.hpp> // for identity
|
||||
#include <boost/utility/enable_if.hpp> // for boost::disable_if
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/// \fn clamp ( T const& val,
|
||||
/// typename boost::mpl::identity<T>::type const& lo,
|
||||
/// typename boost::mpl::identity<T>::type const& hi, Pred p )
|
||||
/// \return the value "val" brought into the range [ lo, hi ]
|
||||
/// using the comparison predicate p.
|
||||
/// If p ( val, lo ) return lo.
|
||||
/// If p ( hi, val ) return hi.
|
||||
/// Otherwise, return the original value.
|
||||
///
|
||||
/// \param val The value to be clamped
|
||||
/// \param lo The lower bound of the range to be clamped to
|
||||
/// \param hi The upper bound of the range to be clamped to
|
||||
/// \param p A predicate to use to compare the values.
|
||||
/// p ( a, b ) returns a boolean.
|
||||
///
|
||||
template<typename T, typename Pred>
|
||||
T const & clamp ( T const& val,
|
||||
typename boost::mpl::identity<T>::type const & lo,
|
||||
typename boost::mpl::identity<T>::type const & hi, Pred p )
|
||||
{
|
||||
// assert ( !p ( hi, lo )); // Can't assert p ( lo, hi ) b/c they might be equal
|
||||
return p ( val, lo ) ? lo : p ( hi, val ) ? hi : val;
|
||||
}
|
||||
|
||||
|
||||
/// \fn clamp ( T const& val,
|
||||
/// typename boost::mpl::identity<T>::type const& lo,
|
||||
/// typename boost::mpl::identity<T>::type const& hi )
|
||||
/// \return the value "val" brought into the range [ lo, hi ].
|
||||
/// If the value is less than lo, return lo.
|
||||
/// If the value is greater than "hi", return hi.
|
||||
/// Otherwise, return the original value.
|
||||
///
|
||||
/// \param val The value to be clamped
|
||||
/// \param lo The lower bound of the range to be clamped to
|
||||
/// \param hi The upper bound of the range to be clamped to
|
||||
///
|
||||
template<typename T>
|
||||
T const& clamp ( const T& val,
|
||||
typename boost::mpl::identity<T>::type const & lo,
|
||||
typename boost::mpl::identity<T>::type const & hi )
|
||||
{
|
||||
return (clamp) ( val, lo, hi, std::less<T>());
|
||||
}
|
||||
|
||||
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
|
||||
/// std::iterator_traits<InputIterator>::value_type lo,
|
||||
/// std::iterator_traits<InputIterator>::value_type hi )
|
||||
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
|
||||
///
|
||||
/// \param first The start of the range of values
|
||||
/// \param last One past the end of the range of input values
|
||||
/// \param out An output iterator to write the clamped values into
|
||||
/// \param lo The lower bound of the range to be clamped to
|
||||
/// \param hi The upper bound of the range to be clamped to
|
||||
///
|
||||
template<typename InputIterator, typename OutputIterator>
|
||||
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
|
||||
typename std::iterator_traits<InputIterator>::value_type lo,
|
||||
typename std::iterator_traits<InputIterator>::value_type hi )
|
||||
{
|
||||
// this could also be written with bind and std::transform
|
||||
while ( first != last )
|
||||
*out++ = clamp ( *first++, lo, hi );
|
||||
return out;
|
||||
}
|
||||
|
||||
/// \fn clamp_range ( const Range &r, OutputIterator out,
|
||||
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
|
||||
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi )
|
||||
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
|
||||
///
|
||||
/// \param r The range of values to be clamped
|
||||
/// \param out An output iterator to write the clamped values into
|
||||
/// \param lo The lower bound of the range to be clamped to
|
||||
/// \param hi The upper bound of the range to be clamped to
|
||||
///
|
||||
template<typename Range, typename OutputIterator>
|
||||
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
|
||||
clamp_range ( const Range &r, OutputIterator out,
|
||||
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
|
||||
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi )
|
||||
{
|
||||
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi );
|
||||
}
|
||||
|
||||
|
||||
/// \fn clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
|
||||
/// std::iterator_traits<InputIterator>::value_type lo,
|
||||
/// std::iterator_traits<InputIterator>::value_type hi, Pred p )
|
||||
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
|
||||
/// using the comparison predicate p.
|
||||
///
|
||||
/// \param first The start of the range of values
|
||||
/// \param last One past the end of the range of input values
|
||||
/// \param out An output iterator to write the clamped values into
|
||||
/// \param lo The lower bound of the range to be clamped to
|
||||
/// \param hi The upper bound of the range to be clamped to
|
||||
/// \param p A predicate to use to compare the values.
|
||||
/// p ( a, b ) returns a boolean.
|
||||
|
||||
///
|
||||
template<typename InputIterator, typename OutputIterator, typename Pred>
|
||||
OutputIterator clamp_range ( InputIterator first, InputIterator last, OutputIterator out,
|
||||
typename std::iterator_traits<InputIterator>::value_type lo,
|
||||
typename std::iterator_traits<InputIterator>::value_type hi, Pred p )
|
||||
{
|
||||
// this could also be written with bind and std::transform
|
||||
while ( first != last )
|
||||
*out++ = clamp ( *first++, lo, hi, p );
|
||||
return out;
|
||||
}
|
||||
|
||||
/// \fn clamp_range ( const Range &r, OutputIterator out,
|
||||
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
|
||||
/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi,
|
||||
/// Pred p )
|
||||
/// \return clamp the sequence of values [first, last) into [ lo, hi ]
|
||||
/// using the comparison predicate p.
|
||||
///
|
||||
/// \param r The range of values to be clamped
|
||||
/// \param out An output iterator to write the clamped values into
|
||||
/// \param lo The lower bound of the range to be clamped to
|
||||
/// \param hi The upper bound of the range to be clamped to
|
||||
/// \param p A predicate to use to compare the values.
|
||||
/// p ( a, b ) returns a boolean.
|
||||
//
|
||||
// Disable this template if the first two parameters are the same type;
|
||||
// In that case, the user will get the two iterator version.
|
||||
template<typename Range, typename OutputIterator, typename Pred>
|
||||
typename boost::disable_if_c<boost::is_same<Range, OutputIterator>::value, OutputIterator>::type
|
||||
clamp_range ( const Range &r, OutputIterator out,
|
||||
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type lo,
|
||||
typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type hi,
|
||||
Pred p )
|
||||
{
|
||||
return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p );
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_CLAMP_HPP
|
||||
91
project/jni/boost/include/boost/algorithm/cxx11/all_of.hpp
Normal file
91
project/jni/boost/include/boost/algorithm/cxx11/all_of.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2008-2012.
|
||||
|
||||
Distributed under the 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 all_of.hpp
|
||||
/// \brief Test ranges to see if all elements match a value or predicate.
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_ALL_OF_HPP
|
||||
#define BOOST_ALGORITHM_ALL_OF_HPP
|
||||
|
||||
#include <algorithm> // for std::all_of, if available
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of all_of if it is available
|
||||
using std::all_of; // Section 25.2.1
|
||||
#else
|
||||
/// \fn all_of ( InputIterator first, InputIterator last, Predicate p )
|
||||
/// \return true if all elements in [first, last) satisfy the predicate 'p'
|
||||
/// \note returns true on an empty range
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param p A predicate for testing the elements of the sequence
|
||||
///
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template<typename InputIterator, typename Predicate>
|
||||
bool all_of ( InputIterator first, InputIterator last, Predicate p )
|
||||
{
|
||||
for ( ; first != last; ++first )
|
||||
if ( !p(*first))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn all_of ( const Range &r, Predicate p )
|
||||
/// \return true if all elements in the range satisfy the predicate 'p'
|
||||
/// \note returns true on an empty range
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename Range, typename Predicate>
|
||||
bool all_of ( const Range &r, Predicate p )
|
||||
{
|
||||
return boost::algorithm::all_of ( boost::begin (r), boost::end (r), p );
|
||||
}
|
||||
|
||||
/// \fn all_of_equal ( InputIterator first, InputIterator last, const T &val )
|
||||
/// \return true if all elements in [first, last) are equal to 'val'
|
||||
/// \note returns true on an empty range
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param val A value to compare against
|
||||
///
|
||||
template<typename InputIterator, typename T>
|
||||
bool all_of_equal ( InputIterator first, InputIterator last, const T &val )
|
||||
{
|
||||
for ( ; first != last; ++first )
|
||||
if ( val != *first )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \fn all_of_equal ( const Range &r, const T &val )
|
||||
/// \return true if all elements in the range are equal to 'val'
|
||||
/// \note returns true on an empty range
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param val A value to compare against
|
||||
///
|
||||
template<typename Range, typename T>
|
||||
bool all_of_equal ( const Range &r, const T &val )
|
||||
{
|
||||
return boost::algorithm::all_of_equal ( boost::begin (r), boost::end (r), val );
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_ALL_OF_HPP
|
||||
90
project/jni/boost/include/boost/algorithm/cxx11/any_of.hpp
Normal file
90
project/jni/boost/include/boost/algorithm/cxx11/any_of.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2008-2012.
|
||||
|
||||
Distributed under the 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
|
||||
*/
|
||||
|
||||
/// \file
|
||||
/// \brief Test ranges to see if any elements match a value or predicate.
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_ANY_OF_HPP
|
||||
#define BOOST_ALGORITHM_ANY_OF_HPP
|
||||
|
||||
#include <algorithm> // for std::any_of, if available
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
// Use the C++11 versions of any_of if it is available
|
||||
#if __cplusplus >= 201103L
|
||||
using std::any_of; // Section 25.2.2
|
||||
#else
|
||||
/// \fn any_of ( InputIterator first, InputIterator last, Predicate p )
|
||||
/// \return true if any of the elements in [first, last) satisfy the predicate
|
||||
/// \note returns false on an empty range
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param p A predicate for testing the elements of the sequence
|
||||
///
|
||||
template<typename InputIterator, typename Predicate>
|
||||
bool any_of ( InputIterator first, InputIterator last, Predicate p )
|
||||
{
|
||||
for ( ; first != last; ++first )
|
||||
if ( p(*first))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn any_of ( const Range &r, Predicate p )
|
||||
/// \return true if any elements in the range satisfy the predicate 'p'
|
||||
/// \note returns false on an empty range
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename Range, typename Predicate>
|
||||
bool any_of ( const Range &r, Predicate p )
|
||||
{
|
||||
return boost::algorithm::any_of (boost::begin (r), boost::end (r), p);
|
||||
}
|
||||
|
||||
/// \fn any_of_equal ( InputIterator first, InputIterator last, const V &val )
|
||||
/// \return true if any of the elements in [first, last) are equal to 'val'
|
||||
/// \note returns false on an empty range
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param val A value to compare against
|
||||
///
|
||||
template<typename InputIterator, typename V>
|
||||
bool any_of_equal ( InputIterator first, InputIterator last, const V &val )
|
||||
{
|
||||
for ( ; first != last; ++first )
|
||||
if ( val == *first )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \fn any_of_equal ( const Range &r, const V &val )
|
||||
/// \return true if any of the elements in the range are equal to 'val'
|
||||
/// \note returns false on an empty range
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param val A value to compare against
|
||||
///
|
||||
template<typename Range, typename V>
|
||||
bool any_of_equal ( const Range &r, const V &val )
|
||||
{
|
||||
return boost::algorithm::any_of_equal (boost::begin (r), boost::end (r), val);
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_ANY_OF_HPP
|
||||
133
project/jni/boost/include/boost/algorithm/cxx11/copy_if.hpp
Normal file
133
project/jni/boost/include/boost/algorithm/cxx11/copy_if.hpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2008-2012.
|
||||
|
||||
Distributed under the 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 copy_if.hpp
|
||||
/// \brief Copy a subset of a sequence to a new sequence
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_COPY_IF_HPP
|
||||
#define BOOST_ALGORITHM_COPY_IF_HPP
|
||||
|
||||
#include <algorithm> // for std::copy_if, if available
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of copy_if if it is available
|
||||
using std::copy_if; // Section 25.3.1
|
||||
#else
|
||||
/// \fn copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
|
||||
/// \brief Copies all the elements from the input range that satisfy the
|
||||
/// predicate to the output range.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template<typename InputIterator, typename OutputIterator, typename Predicate>
|
||||
OutputIterator copy_if ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
|
||||
{
|
||||
for ( ; first != last; ++first )
|
||||
if (p(*first))
|
||||
*result++ = *first;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn copy_if ( const Range &r, OutputIterator result, Predicate p )
|
||||
/// \brief Copies all the elements from the input range that satisfy the
|
||||
/// predicate to the output range.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename Range, typename OutputIterator, typename Predicate>
|
||||
OutputIterator copy_if ( const Range &r, OutputIterator result, Predicate p )
|
||||
{
|
||||
return boost::algorithm::copy_if (boost::begin (r), boost::end(r), result, p);
|
||||
}
|
||||
|
||||
|
||||
/// \fn copy_while ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
|
||||
/// \brief Copies all the elements at the start of the input range that
|
||||
/// satisfy the predicate to the output range.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename InputIterator, typename OutputIterator, typename Predicate>
|
||||
OutputIterator copy_while ( InputIterator first, InputIterator last,
|
||||
OutputIterator result, Predicate p )
|
||||
{
|
||||
for ( ; first != last && p(*first); ++first )
|
||||
*result++ = *first;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \fn copy_while ( const Range &r, OutputIterator result, Predicate p )
|
||||
/// \brief Copies all the elements at the start of the input range that
|
||||
/// satisfy the predicate to the output range.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename Range, typename OutputIterator, typename Predicate>
|
||||
OutputIterator copy_while ( const Range &r, OutputIterator result, Predicate p )
|
||||
{
|
||||
return boost::algorithm::copy_while (boost::begin (r), boost::end(r), result, p);
|
||||
}
|
||||
|
||||
|
||||
/// \fn copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
|
||||
/// \brief Copies all the elements at the start of the input range that do not
|
||||
/// satisfy the predicate to the output range.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename InputIterator, typename OutputIterator, typename Predicate>
|
||||
OutputIterator copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p )
|
||||
{
|
||||
for ( ; first != last && !p(*first); ++first )
|
||||
*result++ = *first;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// \fn copy_until ( const Range &r, OutputIterator result, Predicate p )
|
||||
/// \brief Copies all the elements at the start of the input range that do not
|
||||
/// satisfy the predicate to the output range.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename Range, typename OutputIterator, typename Predicate>
|
||||
OutputIterator copy_until ( const Range &r, OutputIterator result, Predicate p )
|
||||
{
|
||||
return boost::algorithm::copy_until (boost::begin (r), boost::end(r), result, p);
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_COPY_IF_HPP
|
||||
44
project/jni/boost/include/boost/algorithm/cxx11/copy_n.hpp
Normal file
44
project/jni/boost/include/boost/algorithm/cxx11/copy_n.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2011-2012.
|
||||
|
||||
Distributed under the 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 copy_n.hpp
|
||||
/// \brief Copy n items from one sequence to another
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_COPY_N_HPP
|
||||
#define BOOST_ALGORITHM_COPY_N_HPP
|
||||
|
||||
#include <algorithm> // for std::copy_n, if available
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of copy_n if it is available
|
||||
using std::copy_n; // Section 25.3.1
|
||||
#else
|
||||
/// \fn copy_n ( InputIterator first, Size n, OutputIterator result )
|
||||
/// \brief Copies exactly n (n > 0) elements from the range starting at first to
|
||||
/// the range starting at result.
|
||||
/// \return The updated output iterator
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param n The number of elements to copy
|
||||
/// \param result An output iterator to write the results into
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template <typename InputIterator, typename Size, typename OutputIterator>
|
||||
OutputIterator copy_n ( InputIterator first, Size n, OutputIterator result )
|
||||
{
|
||||
for ( ; n > 0; --n, ++first, ++result )
|
||||
*result = *first;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_COPY_IF_HPP
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2011-2012.
|
||||
|
||||
Distributed under the 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 find_if_not.hpp
|
||||
/// \brief Find the first element in a sequence that does not satisfy a predicate.
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_FIND_IF_NOT_HPP
|
||||
#define BOOST_ALGORITHM_FIND_IF_NOT_HPP
|
||||
|
||||
#include <algorithm> // for std::find_if_not, if it exists
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of find_if_not if it is available
|
||||
using std::find_if_not; // Section 25.2.5
|
||||
#else
|
||||
/// \fn find_if_not(InputIterator first, InputIterator last, Predicate p)
|
||||
/// \brief Finds the first element in the sequence that does not satisfy the predicate.
|
||||
/// \return The iterator pointing to the desired element.
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template<typename InputIterator, typename Predicate>
|
||||
InputIterator find_if_not ( InputIterator first, InputIterator last, Predicate p )
|
||||
{
|
||||
for ( ; first != last; ++first )
|
||||
if ( !p(*first))
|
||||
break;
|
||||
return first;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn find_if_not ( const Range &r, Predicate p )
|
||||
/// \brief Finds the first element in the sequence that does not satisfy the predicate.
|
||||
/// \return The iterator pointing to the desired element.
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename Range, typename Predicate>
|
||||
typename boost::range_iterator<const Range>::type find_if_not ( const Range &r, Predicate p )
|
||||
{
|
||||
return boost::algorithm::find_if_not (boost::begin (r), boost::end(r), p);
|
||||
}
|
||||
|
||||
}}
|
||||
#endif // BOOST_ALGORITHM_FIND_IF_NOT_HPP
|
||||
74
project/jni/boost/include/boost/algorithm/cxx11/iota.hpp
Normal file
74
project/jni/boost/include/boost/algorithm/cxx11/iota.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2008-2012.
|
||||
|
||||
Distributed under the 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 iota.hpp
|
||||
/// \brief Generate an increasing series
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_IOTA_HPP
|
||||
#define BOOST_ALGORITHM_IOTA_HPP
|
||||
|
||||
#include <numeric>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of iota if it is available
|
||||
using std::iota; // Section 26.7.6
|
||||
#else
|
||||
/// \fn iota ( ForwardIterator first, ForwardIterator last, T value )
|
||||
/// \brief Generates an increasing sequence of values, and stores them in [first, last)
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param value The initial value of the sequence to be generated
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template <typename ForwardIterator, typename T>
|
||||
void iota ( ForwardIterator first, ForwardIterator last, T value )
|
||||
{
|
||||
for ( ; first != last; ++first, ++value )
|
||||
*first = value;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn iota ( Range &r, T value )
|
||||
/// \brief Generates an increasing sequence of values, and stores them in the input Range.
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param value The initial value of the sequence to be generated
|
||||
///
|
||||
template <typename Range, typename T>
|
||||
void iota ( Range &r, T value )
|
||||
{
|
||||
boost::algorithm::iota (boost::begin(r), boost::end(r), value);
|
||||
}
|
||||
|
||||
|
||||
/// \fn iota_n ( OutputIterator out, T value, std::size_t n )
|
||||
/// \brief Generates an increasing sequence of values, and stores them in the input Range.
|
||||
///
|
||||
/// \param out An output iterator to write the results into
|
||||
/// \param value The initial value of the sequence to be generated
|
||||
/// \param n The number of items to write
|
||||
///
|
||||
template <typename OutputIterator, typename T>
|
||||
OutputIterator iota_n ( OutputIterator out, T value, std::size_t n )
|
||||
{
|
||||
while ( n-- > 0 )
|
||||
*out++ = value++;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_IOTA_HPP
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2011-2012.
|
||||
|
||||
Distributed under the 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 is_partitioned.hpp
|
||||
/// \brief Tell if a sequence is partitioned
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_IS_PARTITIONED_HPP
|
||||
#define BOOST_ALGORITHM_IS_PARTITIONED_HPP
|
||||
|
||||
#include <algorithm> // for std::is_partitioned, if available
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of is_partitioned if it is available
|
||||
using std::is_partitioned; // Section 25.3.13
|
||||
#else
|
||||
/// \fn is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p )
|
||||
/// \brief Tests to see if a sequence is partitioned according to a predicate
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param p The predicate to test the values with
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template <typename InputIterator, typename UnaryPredicate>
|
||||
bool is_partitioned ( InputIterator first, InputIterator last, UnaryPredicate p )
|
||||
{
|
||||
// Run through the part that satisfy the predicate
|
||||
for ( ; first != last; ++first )
|
||||
if ( !p (*first))
|
||||
break;
|
||||
// Now the part that does not satisfy the predicate
|
||||
for ( ; first != last; ++first )
|
||||
if ( p (*first))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn is_partitioned ( const Range &r, UnaryPredicate p )
|
||||
/// \brief Generates an increasing sequence of values, and stores them in the input Range.
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param p The predicate to test the values with
|
||||
///
|
||||
template <typename Range, typename UnaryPredicate>
|
||||
bool is_partitioned ( const Range &r, UnaryPredicate p )
|
||||
{
|
||||
return boost::algorithm::is_partitioned (boost::begin(r), boost::end(r), p);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_IS_PARTITIONED_HPP
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2011-2012.
|
||||
|
||||
Distributed under the 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 is_permutation.hpp
|
||||
/// \brief Is a sequence a permutation of another sequence
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_IS_PERMUTATION_HPP
|
||||
#define BOOST_ALGORITHM_IS_PERMUTATION_HPP
|
||||
|
||||
#include <algorithm> // for std::less, tie, mismatch and is_permutation (if available)
|
||||
#include <utility> // for std::make_pair
|
||||
#include <functional> // for std::equal_to
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/tr1/tr1/tuple> // for tie
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of is_permutation if it is available
|
||||
using std::is_permutation; // Section 25.2.12
|
||||
#else
|
||||
/// \cond DOXYGEN_HIDE
|
||||
namespace detail {
|
||||
template <typename Predicate, typename Iterator>
|
||||
struct value_predicate {
|
||||
value_predicate ( Predicate p, Iterator it ) : p_ ( p ), it_ ( it ) {}
|
||||
|
||||
template <typename T1>
|
||||
bool operator () ( const T1 &t1 ) const { return p_ ( *it_, t1 ); }
|
||||
private:
|
||||
Predicate &p_;
|
||||
Iterator it_;
|
||||
};
|
||||
}
|
||||
/// \endcond
|
||||
|
||||
|
||||
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2, BinaryPredicate p )
|
||||
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param first2 The start of the second sequence
|
||||
/// \param p The predicate to compare elements with
|
||||
///
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate >
|
||||
bool is_permutation ( ForwardIterator1 first1, ForwardIterator1 last1,
|
||||
ForwardIterator2 first2, BinaryPredicate p )
|
||||
{
|
||||
// Skip the common prefix (if any)
|
||||
// std::tie (first1, first2) = std::mismatch (first1, last1, first2, p);
|
||||
std::pair<ForwardIterator1, ForwardIterator2> eq = std::mismatch (first1, last1, first2, p);
|
||||
first1 = eq.first;
|
||||
first2 = eq.second;
|
||||
if ( first1 != last1 ) {
|
||||
// Create last2
|
||||
ForwardIterator2 last2 = first2;
|
||||
std::advance ( last2, std::distance (first1, last1));
|
||||
|
||||
// for each unique value in the sequence [first1,last1), count how many times
|
||||
// it occurs, and make sure it occurs the same number of times in [first2, last2)
|
||||
for ( ForwardIterator1 iter = first1; iter != last1; ++iter ) {
|
||||
detail::value_predicate<BinaryPredicate, ForwardIterator1> pred ( p, iter );
|
||||
|
||||
/* For each value we haven't seen yet... */
|
||||
if ( std::find_if ( first1, iter, pred ) == iter ) {
|
||||
std::size_t dest_count = std::count_if ( first2, last2, pred );
|
||||
if ( dest_count == 0 || dest_count != (std::size_t) std::count_if ( iter, last1, pred ))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 )
|
||||
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param first2 The start of the second sequence
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template< class ForwardIterator1, class ForwardIterator2 >
|
||||
bool is_permutation ( ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 first2 )
|
||||
{
|
||||
// How should I deal with the idea that ForwardIterator1::value_type
|
||||
// and ForwardIterator2::value_type could be different? Define my own comparison predicate?
|
||||
return boost::algorithm::is_permutation ( first, last, first2,
|
||||
std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> ());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// \fn is_permutation ( const Range &r, ForwardIterator first2 )
|
||||
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param first2 The start of the second sequence
|
||||
template <typename Range, typename ForwardIterator>
|
||||
bool is_permutation ( const Range &r, ForwardIterator first2 )
|
||||
{
|
||||
return boost::algorithm::is_permutation (boost::begin (r), boost::end (r), first2 );
|
||||
}
|
||||
|
||||
/// \fn is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
|
||||
/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param first2 The start of the second sequence
|
||||
/// \param pred The predicate to compare elements with
|
||||
///
|
||||
// Disable this template when the first two parameters are the same type
|
||||
// That way the non-range version will be chosen.
|
||||
template <typename Range, typename ForwardIterator, typename BinaryPredicate>
|
||||
typename boost::disable_if_c<boost::is_same<Range, ForwardIterator>::value, bool>::type
|
||||
is_permutation ( const Range &r, ForwardIterator first2, BinaryPredicate pred )
|
||||
{
|
||||
return boost::algorithm::is_permutation (boost::begin (r), boost::end (r), first2, pred );
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_IS_PERMUTATION_HPP
|
||||
287
project/jni/boost/include/boost/algorithm/cxx11/is_sorted.hpp
Normal file
287
project/jni/boost/include/boost/algorithm/cxx11/is_sorted.hpp
Normal file
@@ -0,0 +1,287 @@
|
||||
// Copyright (c) 2010 Nuovation System Designs, LLC
|
||||
// Grant Erickson <gerickson@nuovations.com>
|
||||
//
|
||||
// Reworked somewhat by Marshall Clow; August 2010
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.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 latest version.
|
||||
//
|
||||
|
||||
#ifndef BOOST_ALGORITHM_ORDERED_HPP
|
||||
#define BOOST_ALGORITHM_ORDERED_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of is_sorted/is_sorted_until if they are available
|
||||
using std::is_sorted_until; // Section 25.4.1.5
|
||||
using std::is_sorted; // Section 25.4.1.5
|
||||
#else
|
||||
/// \fn is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p )
|
||||
/// \return the point in the sequence [first, last) where the elements are unordered
|
||||
/// (according to the comparison predicate 'p').
|
||||
///
|
||||
/// \param first The start of the sequence to be tested.
|
||||
/// \param last One past the end of the sequence
|
||||
/// \param p A binary predicate that returns true if two elements are ordered.
|
||||
///
|
||||
template <typename ForwardIterator, typename Pred>
|
||||
ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last, Pred p )
|
||||
{
|
||||
if ( first == last ) return last; // the empty sequence is ordered
|
||||
ForwardIterator next = first;
|
||||
while ( ++next != last )
|
||||
{
|
||||
if ( p ( *next, *first ))
|
||||
return next;
|
||||
first = next;
|
||||
}
|
||||
return last;
|
||||
}
|
||||
|
||||
/// \fn is_sorted_until ( ForwardIterator first, ForwardIterator last )
|
||||
/// \return the point in the sequence [first, last) where the elements are unordered
|
||||
///
|
||||
/// \param first The start of the sequence to be tested.
|
||||
/// \param last One past the end of the sequence
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
ForwardIterator is_sorted_until ( ForwardIterator first, ForwardIterator last )
|
||||
{
|
||||
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
return boost::algorithm::is_sorted_until ( first, last, std::less<value_type>());
|
||||
}
|
||||
|
||||
|
||||
/// \fn is_sorted ( ForwardIterator first, ForwardIterator last, Pred p )
|
||||
/// \return whether or not the entire sequence is sorted
|
||||
///
|
||||
/// \param first The start of the sequence to be tested.
|
||||
/// \param last One past the end of the sequence
|
||||
/// \param p A binary predicate that returns true if two elements are ordered.
|
||||
///
|
||||
template <typename ForwardIterator, typename Pred>
|
||||
bool is_sorted ( ForwardIterator first, ForwardIterator last, Pred p )
|
||||
{
|
||||
return boost::algorithm::is_sorted_until (first, last, p) == last;
|
||||
}
|
||||
|
||||
/// \fn is_sorted ( ForwardIterator first, ForwardIterator last )
|
||||
/// \return whether or not the entire sequence is sorted
|
||||
///
|
||||
/// \param first The start of the sequence to be tested.
|
||||
/// \param last One past the end of the sequence
|
||||
///
|
||||
template <typename ForwardIterator>
|
||||
bool is_sorted ( ForwardIterator first, ForwardIterator last )
|
||||
{
|
||||
return boost::algorithm::is_sorted_until (first, last) == last;
|
||||
}
|
||||
#endif
|
||||
|
||||
///
|
||||
/// -- Range based versions of the C++11 functions
|
||||
///
|
||||
|
||||
/// \fn is_sorted_until ( const R &range, Pred p )
|
||||
/// \return the point in the range R where the elements are unordered
|
||||
/// (according to the comparison predicate 'p').
|
||||
///
|
||||
/// \param range The range to be tested.
|
||||
/// \param p A binary predicate that returns true if two elements are ordered.
|
||||
///
|
||||
template <typename R, typename Pred>
|
||||
typename boost::lazy_disable_if_c<
|
||||
boost::is_same<R, Pred>::value,
|
||||
typename boost::range_iterator<const R>
|
||||
>::type is_sorted_until ( const R &range, Pred p )
|
||||
{
|
||||
return boost::algorithm::is_sorted_until ( boost::begin ( range ), boost::end ( range ), p );
|
||||
}
|
||||
|
||||
|
||||
/// \fn is_sorted_until ( const R &range )
|
||||
/// \return the point in the range R where the elements are unordered
|
||||
///
|
||||
/// \param range The range to be tested.
|
||||
///
|
||||
template <typename R>
|
||||
typename boost::range_iterator<const R>::type is_sorted_until ( const R &range )
|
||||
{
|
||||
return boost::algorithm::is_sorted_until ( boost::begin ( range ), boost::end ( range ));
|
||||
}
|
||||
|
||||
/// \fn is_sorted ( const R &range, Pred p )
|
||||
/// \return whether or not the entire range R is sorted
|
||||
/// (according to the comparison predicate 'p').
|
||||
///
|
||||
/// \param range The range to be tested.
|
||||
/// \param p A binary predicate that returns true if two elements are ordered.
|
||||
///
|
||||
template <typename R, typename Pred>
|
||||
typename boost::lazy_disable_if_c< boost::is_same<R, Pred>::value, boost::mpl::identity<bool> >::type
|
||||
is_sorted ( const R &range, Pred p )
|
||||
{
|
||||
return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range ), p );
|
||||
}
|
||||
|
||||
|
||||
/// \fn is_sorted ( const R &range )
|
||||
/// \return whether or not the entire range R is sorted
|
||||
///
|
||||
/// \param range The range to be tested.
|
||||
///
|
||||
template <typename R>
|
||||
bool is_sorted ( const R &range )
|
||||
{
|
||||
return boost::algorithm::is_sorted ( boost::begin ( range ), boost::end ( range ));
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// -- Range based versions of the C++11 functions
|
||||
///
|
||||
|
||||
/// \fn is_increasing ( ForwardIterator first, ForwardIterator last )
|
||||
/// \return true if the entire sequence is increasing; i.e, each item is greater than or
|
||||
/// equal to the previous one.
|
||||
///
|
||||
/// \param first The start of the sequence to be tested.
|
||||
/// \param last One past the end of the sequence
|
||||
///
|
||||
/// \note This function will return true for sequences that contain items that compare
|
||||
/// equal. If that is not what you intended, you should use is_strictly_increasing instead.
|
||||
template <typename ForwardIterator>
|
||||
bool is_increasing ( ForwardIterator first, ForwardIterator last )
|
||||
{
|
||||
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
return boost::algorithm::is_sorted (first, last, std::less<value_type>());
|
||||
}
|
||||
|
||||
|
||||
/// \fn is_increasing ( const R &range )
|
||||
/// \return true if the entire sequence is increasing; i.e, each item is greater than or
|
||||
/// equal to the previous one.
|
||||
///
|
||||
/// \param range The range to be tested.
|
||||
///
|
||||
/// \note This function will return true for sequences that contain items that compare
|
||||
/// equal. If that is not what you intended, you should use is_strictly_increasing instead.
|
||||
template <typename R>
|
||||
bool is_increasing ( const R &range )
|
||||
{
|
||||
return is_increasing ( boost::begin ( range ), boost::end ( range ));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// \fn is_decreasing ( ForwardIterator first, ForwardIterator last )
|
||||
/// \return true if the entire sequence is decreasing; i.e, each item is less than
|
||||
/// or equal to the previous one.
|
||||
///
|
||||
/// \param first The start of the sequence to be tested.
|
||||
/// \param last One past the end of the sequence
|
||||
///
|
||||
/// \note This function will return true for sequences that contain items that compare
|
||||
/// equal. If that is not what you intended, you should use is_strictly_decreasing instead.
|
||||
template <typename ForwardIterator>
|
||||
bool is_decreasing ( ForwardIterator first, ForwardIterator last )
|
||||
{
|
||||
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
return boost::algorithm::is_sorted (first, last, std::greater<value_type>());
|
||||
}
|
||||
|
||||
/// \fn is_decreasing ( const R &range )
|
||||
/// \return true if the entire sequence is decreasing; i.e, each item is less than
|
||||
/// or equal to the previous one.
|
||||
///
|
||||
/// \param range The range to be tested.
|
||||
///
|
||||
/// \note This function will return true for sequences that contain items that compare
|
||||
/// equal. If that is not what you intended, you should use is_strictly_decreasing instead.
|
||||
template <typename R>
|
||||
bool is_decreasing ( const R &range )
|
||||
{
|
||||
return is_decreasing ( boost::begin ( range ), boost::end ( range ));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// \fn is_strictly_increasing ( ForwardIterator first, ForwardIterator last )
|
||||
/// \return true if the entire sequence is strictly increasing; i.e, each item is greater
|
||||
/// than the previous one
|
||||
///
|
||||
/// \param first The start of the sequence to be tested.
|
||||
/// \param last One past the end of the sequence
|
||||
///
|
||||
/// \note This function will return false for sequences that contain items that compare
|
||||
/// equal. If that is not what you intended, you should use is_increasing instead.
|
||||
template <typename ForwardIterator>
|
||||
bool is_strictly_increasing ( ForwardIterator first, ForwardIterator last )
|
||||
{
|
||||
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
return boost::algorithm::is_sorted (first, last, std::less_equal<value_type>());
|
||||
}
|
||||
|
||||
/// \fn is_strictly_increasing ( const R &range )
|
||||
/// \return true if the entire sequence is strictly increasing; i.e, each item is greater
|
||||
/// than the previous one
|
||||
///
|
||||
/// \param range The range to be tested.
|
||||
///
|
||||
/// \note This function will return false for sequences that contain items that compare
|
||||
/// equal. If that is not what you intended, you should use is_increasing instead.
|
||||
template <typename R>
|
||||
bool is_strictly_increasing ( const R &range )
|
||||
{
|
||||
return is_strictly_increasing ( boost::begin ( range ), boost::end ( range ));
|
||||
}
|
||||
|
||||
|
||||
/// \fn is_strictly_decreasing ( ForwardIterator first, ForwardIterator last )
|
||||
/// \return true if the entire sequence is strictly decreasing; i.e, each item is less than
|
||||
/// the previous one
|
||||
///
|
||||
/// \param first The start of the sequence to be tested.
|
||||
/// \param last One past the end of the sequence
|
||||
///
|
||||
/// \note This function will return false for sequences that contain items that compare
|
||||
/// equal. If that is not what you intended, you should use is_decreasing instead.
|
||||
template <typename ForwardIterator>
|
||||
bool is_strictly_decreasing ( ForwardIterator first, ForwardIterator last )
|
||||
{
|
||||
typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
|
||||
return boost::algorithm::is_sorted (first, last, std::greater_equal<value_type>());
|
||||
}
|
||||
|
||||
/// \fn is_strictly_decreasing ( const R &range )
|
||||
/// \return true if the entire sequence is strictly decreasing; i.e, each item is less than
|
||||
/// the previous one
|
||||
///
|
||||
/// \param range The range to be tested.
|
||||
///
|
||||
/// \note This function will return false for sequences that contain items that compare
|
||||
/// equal. If that is not what you intended, you should use is_decreasing instead.
|
||||
template <typename R>
|
||||
bool is_strictly_decreasing ( const R &range )
|
||||
{
|
||||
return is_strictly_decreasing ( boost::begin ( range ), boost::end ( range ));
|
||||
}
|
||||
|
||||
}} // namespace boost
|
||||
|
||||
#endif // BOOST_ALGORITHM_ORDERED_HPP
|
||||
88
project/jni/boost/include/boost/algorithm/cxx11/none_of.hpp
Normal file
88
project/jni/boost/include/boost/algorithm/cxx11/none_of.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2008-2012.
|
||||
|
||||
Distributed under the 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 none_of.hpp
|
||||
/// \brief Test ranges to see if no elements match a value or predicate.
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_NONE_OF_HPP
|
||||
#define BOOST_ALGORITHM_NONE_OF_HPP
|
||||
|
||||
#include <algorithm> // for std::none_of, if available
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
// Use the C++11 versions of the none_of if it is available
|
||||
#if __cplusplus >= 201103L
|
||||
using std::none_of; // Section 25.2.3
|
||||
#else
|
||||
/// \fn none_of ( InputIterator first, InputIterator last, Predicate p )
|
||||
/// \return true if none of the elements in [first, last) satisfy the predicate 'p'
|
||||
/// \note returns true on an empty range
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param p A predicate for testing the elements of the sequence
|
||||
///
|
||||
template<typename InputIterator, typename Predicate>
|
||||
bool none_of ( InputIterator first, InputIterator last, Predicate p )
|
||||
{
|
||||
for ( ; first != last; ++first )
|
||||
if ( p(*first))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn none_of ( const Range &r, Predicate p )
|
||||
/// \return true if none of the elements in the range satisfy the predicate 'p'
|
||||
/// \note returns true on an empty range
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename Range, typename Predicate>
|
||||
bool none_of ( const Range &r, Predicate p )
|
||||
{
|
||||
return boost::algorithm::none_of (boost::begin (r), boost::end (r), p );
|
||||
}
|
||||
|
||||
/// \fn none_of_equal ( InputIterator first, InputIterator last, const V &val )
|
||||
/// \return true if none of the elements in [first, last) are equal to 'val'
|
||||
/// \note returns true on an empty range
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param val A value to compare against
|
||||
///
|
||||
template<typename InputIterator, typename V>
|
||||
bool none_of_equal ( InputIterator first, InputIterator last, const V &val )
|
||||
{
|
||||
for ( ; first != last; ++first )
|
||||
if ( val == *first )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// \fn none_of_equal ( const Range &r, const V &val )
|
||||
/// \return true if none of the elements in the range are equal to 'val'
|
||||
/// \note returns true on an empty range
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param val A value to compare against
|
||||
///
|
||||
template<typename Range, typename V>
|
||||
bool none_of_equal ( const Range &r, const V & val )
|
||||
{
|
||||
return boost::algorithm::none_of_equal (boost::begin (r), boost::end (r), val);
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_NONE_OF_HPP
|
||||
82
project/jni/boost/include/boost/algorithm/cxx11/one_of.hpp
Normal file
82
project/jni/boost/include/boost/algorithm/cxx11/one_of.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2008-2012.
|
||||
|
||||
Distributed under the 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 one_of.hpp
|
||||
/// \brief Test ranges to see if only one element matches a value or predicate.
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_ONE_OF_HPP
|
||||
#define BOOST_ALGORITHM_ONE_OF_HPP
|
||||
|
||||
#include <algorithm> // for std::find and std::find_if
|
||||
#include <boost/algorithm/cxx11/none_of.hpp>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/// \fn one_of ( InputIterator first, InputIterator last, Predicate p )
|
||||
/// \return true if the predicate 'p' is true for exactly one item in [first, last).
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param p A predicate for testing the elements of the sequence
|
||||
///
|
||||
template<typename InputIterator, typename Predicate>
|
||||
bool one_of ( InputIterator first, InputIterator last, Predicate p )
|
||||
{
|
||||
InputIterator i = std::find_if (first, last, p);
|
||||
if (i == last)
|
||||
return false; // Didn't occur at all
|
||||
return boost::algorithm::none_of (++i, last, p);
|
||||
}
|
||||
|
||||
/// \fn one_of ( const Range &r, Predicate p )
|
||||
/// \return true if the predicate 'p' is true for exactly one item in the range.
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param p A predicate for testing the elements of the range
|
||||
///
|
||||
template<typename Range, typename Predicate>
|
||||
bool one_of ( const Range &r, Predicate p )
|
||||
{
|
||||
return boost::algorithm::one_of ( boost::begin (r), boost::end (r), p );
|
||||
}
|
||||
|
||||
|
||||
/// \fn one_of_equal ( InputIterator first, InputIterator last, const V &val )
|
||||
/// \return true if the value 'val' exists only once in [first, last).
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param val A value to compare against
|
||||
///
|
||||
template<typename InputIterator, typename V>
|
||||
bool one_of_equal ( InputIterator first, InputIterator last, const V &val )
|
||||
{
|
||||
InputIterator i = std::find (first, last, val); // find first occurrence of 'val'
|
||||
if (i == last)
|
||||
return false; // Didn't occur at all
|
||||
return boost::algorithm::none_of_equal (++i, last, val);
|
||||
}
|
||||
|
||||
/// \fn one_of_equal ( const Range &r, const V &val )
|
||||
/// \return true if the value 'val' exists only once in the range.
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param val A value to compare against
|
||||
///
|
||||
template<typename Range, typename V>
|
||||
bool one_of_equal ( const Range &r, const V &val )
|
||||
{
|
||||
return boost::algorithm::one_of_equal ( boost::begin (r), boost::end (r), val );
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_ALL_HPP
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2011-2012.
|
||||
|
||||
Distributed under the 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 partition_copy.hpp
|
||||
/// \brief Copy a subset of a sequence to a new sequence
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_PARTITION_COPY_HPP
|
||||
#define BOOST_ALGORITHM_PARTITION_COPY_HPP
|
||||
|
||||
#include <algorithm> // for std::partition_copy, if available
|
||||
#include <utility> // for make_pair
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of partition_copy if it is available
|
||||
using std::partition_copy; // Section 25.3.13
|
||||
#else
|
||||
/// \fn partition_copy ( InputIterator first, InputIterator last,
|
||||
/// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
|
||||
/// \brief Copies the elements that satisfy the predicate p from the range [first, last)
|
||||
/// to the range beginning at d_first_true, and
|
||||
/// copies the elements that do not satisfy p to the range beginning at d_first_false.
|
||||
///
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param out_true An output iterator to write the elements that satisfy the predicate into
|
||||
/// \param out_false An output iterator to write the elements that do not satisfy the predicate into
|
||||
/// \param p A predicate for dividing the elements of the input sequence.
|
||||
///
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template <typename InputIterator,
|
||||
typename OutputIterator1, typename OutputIterator2, typename UnaryPredicate>
|
||||
std::pair<OutputIterator1, OutputIterator2>
|
||||
partition_copy ( InputIterator first, InputIterator last,
|
||||
OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
|
||||
{
|
||||
for ( ; first != last; ++first )
|
||||
if ( p (*first))
|
||||
*out_true++ = *first;
|
||||
else
|
||||
*out_false++ = *first;
|
||||
return std::pair<OutputIterator1, OutputIterator2> ( out_true, out_false );
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn partition_copy ( const Range &r,
|
||||
/// OutputIterator1 out_true, OutputIterator2 out_false, UnaryPredicate p )
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param out_true An output iterator to write the elements that satisfy the predicate into
|
||||
/// \param out_false An output iterator to write the elements that do not satisfy the predicate into
|
||||
/// \param p A predicate for dividing the elements of the input sequence.
|
||||
///
|
||||
template <typename Range, typename OutputIterator1, typename OutputIterator2,
|
||||
typename UnaryPredicate>
|
||||
std::pair<OutputIterator1, OutputIterator2>
|
||||
partition_copy ( const Range &r, OutputIterator1 out_true, OutputIterator2 out_false,
|
||||
UnaryPredicate p )
|
||||
{
|
||||
return boost::algorithm::partition_copy
|
||||
(boost::begin(r), boost::end(r), out_true, out_false, p );
|
||||
}
|
||||
|
||||
}} // namespace boost and algorithm
|
||||
|
||||
#endif // BOOST_ALGORITHM_PARTITION_COPY_HPP
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2011-2012.
|
||||
|
||||
Distributed under the 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 partition_point.hpp
|
||||
/// \brief Find the partition point in a sequence
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_PARTITION_POINT_HPP
|
||||
#define BOOST_ALGORITHM_PARTITION_POINT_HPP
|
||||
|
||||
#include <algorithm> // for std::partition_point, if available
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// Use the C++11 versions of partition_point if it is available
|
||||
using std::partition_point; // Section 25.3.13
|
||||
#else
|
||||
/// \fn partition_point ( ForwardIterator first, ForwardIterator last, Predicate p )
|
||||
/// \brief Given a partitioned range, returns the partition point, i.e, the first element
|
||||
/// that does not satisfy p
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param p The predicate to test the values with
|
||||
/// \note This function is part of the C++2011 standard library.
|
||||
/// We will use the standard one if it is available,
|
||||
/// otherwise we have our own implementation.
|
||||
template <typename ForwardIterator, typename Predicate>
|
||||
ForwardIterator partition_point ( ForwardIterator first, ForwardIterator last, Predicate p )
|
||||
{
|
||||
std::size_t dist = std::distance ( first, last );
|
||||
while ( first != last ) {
|
||||
std::size_t d2 = dist / 2;
|
||||
ForwardIterator ret_val = first;
|
||||
std::advance (ret_val, d2);
|
||||
if (p (*ret_val)) {
|
||||
first = ++ret_val;
|
||||
dist -= d2 + 1;
|
||||
}
|
||||
else {
|
||||
last = ret_val;
|
||||
dist = d2;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \fn partition_point ( Range &r, Predicate p )
|
||||
/// \brief Given a partitioned range, returns the partition point
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param p The predicate to test the values with
|
||||
///
|
||||
template <typename Range, typename Predicate>
|
||||
typename boost::range_iterator<Range> partition_point ( Range &r, Predicate p )
|
||||
{
|
||||
return boost::algorithm::partition_point (boost::begin(r), boost::end(r), p);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_PARTITION_POINT_HPP
|
||||
269
project/jni/boost/include/boost/algorithm/hex.hpp
Normal file
269
project/jni/boost/include/boost/algorithm/hex.hpp
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2011-2012.
|
||||
|
||||
Distributed under the 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 Nevin for his comments/help.
|
||||
*/
|
||||
|
||||
/*
|
||||
General problem - turn a sequence of integral types into a sequence of hexadecimal characters.
|
||||
- and back.
|
||||
|
||||
TO DO:
|
||||
1. these should really only work on integral types. (see the >> and << operations)
|
||||
-- this is done, I think.
|
||||
2. The 'value_type_or_char' struct is really a hack.
|
||||
-- but it's a better hack now that it works with back_insert_iterators
|
||||
*/
|
||||
|
||||
/// \file hex.hpp
|
||||
/// \brief Convert sequence of integral types into a sequence of hexadecimal
|
||||
/// characters and back. Based on the MySQL functions HEX and UNHEX
|
||||
/// \author Marshall Clow
|
||||
|
||||
#ifndef BOOST_ALGORITHM_HEXHPP
|
||||
#define BOOST_ALGORITHM_HEXHPP
|
||||
|
||||
#include <iterator> // for std::iterator_traits
|
||||
#include <stdexcept>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/exception/all.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/*!
|
||||
\struct hex_decode_error
|
||||
\brief Base exception class for all hex decoding errors
|
||||
|
||||
\struct non_hex_input
|
||||
\brief Thrown when a non-hex value (0-9, A-F) encountered when decoding.
|
||||
Contains the offending character
|
||||
|
||||
\struct not_enough_input
|
||||
\brief Thrown when the input sequence unexpectedly ends
|
||||
|
||||
*/
|
||||
struct hex_decode_error : virtual boost::exception, virtual std::exception {};
|
||||
struct not_enough_input : virtual hex_decode_error {};
|
||||
struct non_hex_input : virtual hex_decode_error {};
|
||||
typedef boost::error_info<struct bad_char_,char> bad_char;
|
||||
|
||||
namespace detail {
|
||||
/// \cond DOXYGEN_HIDE
|
||||
|
||||
template <typename T, typename OutputIterator>
|
||||
OutputIterator encode_one ( T val, OutputIterator out ) {
|
||||
const std::size_t num_hex_digits = 2 * sizeof ( T );
|
||||
char res [ num_hex_digits ];
|
||||
char *p = res + num_hex_digits;
|
||||
for ( std::size_t i = 0; i < num_hex_digits; ++i, val >>= 4 )
|
||||
*--p = "0123456789ABCDEF" [ val & 0x0F ];
|
||||
return std::copy ( res, res + num_hex_digits, out );
|
||||
}
|
||||
|
||||
// this needs to be in an un-named namespace because it is not a template
|
||||
// and might get included in several compilation units. This could cause
|
||||
// multiple definition errors at link time.
|
||||
namespace {
|
||||
unsigned hex_char_to_int ( char c ) {
|
||||
if ( c >= '0' && c <= '9' ) return c - '0';
|
||||
if ( c >= 'A' && c <= 'F' ) return c - 'A' + 10;
|
||||
if ( c >= 'a' && c <= 'f' ) return c - 'a' + 10;
|
||||
BOOST_THROW_EXCEPTION (non_hex_input() << bad_char (c));
|
||||
return 0; // keep dumb compilers happy
|
||||
}
|
||||
}
|
||||
|
||||
// My own iterator_traits class.
|
||||
// It is here so that I can "reach inside" some kinds of output iterators
|
||||
// and get the type to write.
|
||||
template <typename Iterator>
|
||||
struct hex_iterator_traits {
|
||||
typedef typename std::iterator_traits<Iterator>::value_type value_type;
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
struct hex_iterator_traits< std::back_insert_iterator<Container> > {
|
||||
typedef typename Container::value_type value_type;
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
struct hex_iterator_traits< std::front_insert_iterator<Container> > {
|
||||
typedef typename Container::value_type value_type;
|
||||
};
|
||||
|
||||
template<typename Container>
|
||||
struct hex_iterator_traits< std::insert_iterator<Container> > {
|
||||
typedef typename Container::value_type value_type;
|
||||
};
|
||||
|
||||
// ostream_iterators have three template parameters.
|
||||
// The first one is the output type, the second one is the character type of
|
||||
// the underlying stream, the third is the character traits.
|
||||
// We only care about the first one.
|
||||
template<typename T, typename charType, typename traits>
|
||||
struct hex_iterator_traits< std::ostream_iterator<T, charType, traits> > {
|
||||
typedef T value_type;
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
bool iter_end ( Iterator current, Iterator last ) { return current == last; }
|
||||
|
||||
template <typename T>
|
||||
bool ptr_end ( const T* ptr, const T* /*end*/ ) { return *ptr == '\0'; }
|
||||
|
||||
// What can we assume here about the inputs?
|
||||
// is std::iterator_traits<InputIterator>::value_type always 'char' ?
|
||||
// Could it be wchar_t, say? Does it matter?
|
||||
// We are assuming ASCII for the values - but what about the storage?
|
||||
template <typename InputIterator, typename OutputIterator, typename EndPred>
|
||||
typename boost::enable_if<boost::is_integral<typename hex_iterator_traits<OutputIterator>::value_type>, OutputIterator>::type
|
||||
decode_one ( InputIterator &first, InputIterator last, OutputIterator out, EndPred pred ) {
|
||||
typedef typename hex_iterator_traits<OutputIterator>::value_type T;
|
||||
T res (0);
|
||||
|
||||
// Need to make sure that we get can read that many chars here.
|
||||
for ( std::size_t i = 0; i < 2 * sizeof ( T ); ++i, ++first ) {
|
||||
if ( pred ( first, last ))
|
||||
BOOST_THROW_EXCEPTION (not_enough_input ());
|
||||
res = ( 16 * res ) + hex_char_to_int (static_cast<char> (*first));
|
||||
}
|
||||
|
||||
*out = res;
|
||||
return ++out;
|
||||
}
|
||||
/// \endcond
|
||||
}
|
||||
|
||||
|
||||
/// \fn hex ( InputIterator first, InputIterator last, OutputIterator out )
|
||||
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param out An output iterator to the results into
|
||||
/// \return The updated output iterator
|
||||
/// \note Based on the MySQL function of the same name
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<InputIterator>::value_type>, OutputIterator>::type
|
||||
hex ( InputIterator first, InputIterator last, OutputIterator out ) {
|
||||
for ( ; first != last; ++first )
|
||||
out = detail::encode_one ( *first, out );
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/// \fn hex ( const T *ptr, OutputIterator out )
|
||||
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
|
||||
///
|
||||
/// \param ptr A pointer to a 0-terminated sequence of data.
|
||||
/// \param out An output iterator to the results into
|
||||
/// \return The updated output iterator
|
||||
/// \note Based on the MySQL function of the same name
|
||||
template <typename T, typename OutputIterator>
|
||||
typename boost::enable_if<boost::is_integral<T>, OutputIterator>::type
|
||||
hex ( const T *ptr, OutputIterator out ) {
|
||||
while ( *ptr )
|
||||
out = detail::encode_one ( *ptr++, out );
|
||||
return out;
|
||||
}
|
||||
|
||||
/// \fn hex ( const Range &r, OutputIterator out )
|
||||
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param out An output iterator to the results into
|
||||
/// \return The updated output iterator
|
||||
/// \note Based on the MySQL function of the same name
|
||||
template <typename Range, typename OutputIterator>
|
||||
typename boost::enable_if<boost::is_integral<typename detail::hex_iterator_traits<typename Range::iterator>::value_type>, OutputIterator>::type
|
||||
hex ( const Range &r, OutputIterator out ) {
|
||||
return hex (boost::begin(r), boost::end(r), out);
|
||||
}
|
||||
|
||||
|
||||
/// \fn unhex ( InputIterator first, InputIterator last, OutputIterator out )
|
||||
/// \brief Converts a sequence of hexadecimal characters into a sequence of integers.
|
||||
///
|
||||
/// \param first The start of the input sequence
|
||||
/// \param last One past the end of the input sequence
|
||||
/// \param out An output iterator to the results into
|
||||
/// \return The updated output iterator
|
||||
/// \note Based on the MySQL function of the same name
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
OutputIterator unhex ( InputIterator first, InputIterator last, OutputIterator out ) {
|
||||
while ( first != last )
|
||||
out = detail::decode_one ( first, last, out, detail::iter_end<InputIterator> );
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/// \fn unhex ( const T *ptr, OutputIterator out )
|
||||
/// \brief Converts a sequence of hexadecimal characters into a sequence of integers.
|
||||
///
|
||||
/// \param ptr A pointer to a null-terminated input sequence.
|
||||
/// \param out An output iterator to the results into
|
||||
/// \return The updated output iterator
|
||||
/// \note Based on the MySQL function of the same name
|
||||
template <typename T, typename OutputIterator>
|
||||
OutputIterator unhex ( const T *ptr, OutputIterator out ) {
|
||||
typedef typename detail::hex_iterator_traits<OutputIterator>::value_type OutputType;
|
||||
// If we run into the terminator while decoding, we will throw a
|
||||
// malformed input exception. It would be nicer to throw a 'Not enough input'
|
||||
// exception - but how much extra work would that require?
|
||||
while ( *ptr )
|
||||
out = detail::decode_one ( ptr, (const T *) NULL, out, detail::ptr_end<T> );
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/// \fn OutputIterator unhex ( const Range &r, OutputIterator out )
|
||||
/// \brief Converts a sequence of hexadecimal characters into a sequence of integers.
|
||||
///
|
||||
/// \param r The input range
|
||||
/// \param out An output iterator to the results into
|
||||
/// \return The updated output iterator
|
||||
/// \note Based on the MySQL function of the same name
|
||||
template <typename Range, typename OutputIterator>
|
||||
OutputIterator unhex ( const Range &r, OutputIterator out ) {
|
||||
return unhex (boost::begin(r), boost::end(r), out);
|
||||
}
|
||||
|
||||
|
||||
/// \fn String hex ( const String &input )
|
||||
/// \brief Converts a sequence of integral types into a hexadecimal sequence of characters.
|
||||
///
|
||||
/// \param input A container to be converted
|
||||
/// \return A container with the encoded text
|
||||
template<typename String>
|
||||
String hex ( const String &input ) {
|
||||
String output;
|
||||
output.reserve (input.size () * (2 * sizeof (typename String::value_type)));
|
||||
(void) hex (input, std::back_inserter (output));
|
||||
return output;
|
||||
}
|
||||
|
||||
/// \fn String unhex ( const String &input )
|
||||
/// \brief Converts a sequence of hexadecimal characters into a sequence of characters.
|
||||
///
|
||||
/// \param input A container to be converted
|
||||
/// \return A container with the decoded text
|
||||
template<typename String>
|
||||
String unhex ( const String &input ) {
|
||||
String output;
|
||||
output.reserve (input.size () / (2 * sizeof (typename String::value_type)));
|
||||
(void) unhex (input, std::back_inserter (output));
|
||||
return output;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_HEXHPP
|
||||
@@ -99,8 +99,10 @@ namespace boost {
|
||||
|
||||
// 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;
|
||||
if (comp(first, min_result)) {
|
||||
min_result = first;
|
||||
potential_min_result = last;
|
||||
}
|
||||
else if (comp(max_result, first))
|
||||
max_result = first;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2010-2012.
|
||||
|
||||
Distributed under the 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_ALGORITHM_BOYER_MOORE_SEARCH_HPP
|
||||
#define BOOST_ALGORITHM_BOYER_MOORE_SEARCH_HPP
|
||||
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/algorithm/searching/detail/bm_traits.hpp>
|
||||
#include <boost/algorithm/searching/detail/debugging.hpp>
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/*
|
||||
A templated version of the boyer-moore searching algorithm.
|
||||
|
||||
References:
|
||||
http://www.cs.utexas.edu/users/moore/best-ideas/string-searching/
|
||||
http://www.cs.utexas.edu/~moore/publications/fstrpos.pdf
|
||||
|
||||
Explanations:
|
||||
http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm
|
||||
http://www.movsd.com/bm.htm
|
||||
http://www.cs.ucdavis.edu/~gusfield/cs224f09/bnotes.pdf
|
||||
|
||||
The Boyer-Moore search algorithm uses two tables, a "bad character" table
|
||||
to tell how far to skip ahead when it hits a character that is not in the pattern,
|
||||
and a "good character" table to tell how far to skip ahead when it hits a
|
||||
mismatch on a character that _is_ in the pattern.
|
||||
|
||||
Requirements:
|
||||
* Random access iterators
|
||||
* The two iterator types (patIter and corpusIter) must
|
||||
"point to" the same underlying type and be comparable.
|
||||
* Additional requirements may be imposed but the skip table, such as:
|
||||
** Numeric type (array-based skip table)
|
||||
** Hashable type (map-based skip table)
|
||||
*/
|
||||
|
||||
template <typename patIter, typename traits = detail::BM_traits<patIter> >
|
||||
class boyer_moore {
|
||||
typedef typename std::iterator_traits<patIter>::difference_type difference_type;
|
||||
public:
|
||||
boyer_moore ( patIter first, patIter last )
|
||||
: pat_first ( first ), pat_last ( last ),
|
||||
k_pattern_length ( std::distance ( pat_first, pat_last )),
|
||||
skip_ ( k_pattern_length, -1 ),
|
||||
suffix_ ( k_pattern_length + 1 )
|
||||
{
|
||||
this->build_skip_table ( first, last );
|
||||
this->build_suffix_table ( first, last );
|
||||
}
|
||||
|
||||
~boyer_moore () {}
|
||||
|
||||
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last )
|
||||
/// \brief Searches the corpus for the pattern that was passed into the constructor
|
||||
///
|
||||
/// \param corpus_first The start of the data to search (Random Access Iterator)
|
||||
/// \param corpus_last One past the end of the data to search
|
||||
///
|
||||
template <typename corpusIter>
|
||||
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ) const {
|
||||
BOOST_STATIC_ASSERT (( boost::is_same<
|
||||
typename std::iterator_traits<patIter>::value_type,
|
||||
typename std::iterator_traits<corpusIter>::value_type>::value ));
|
||||
|
||||
if ( corpus_first == corpus_last ) return corpus_last; // if nothing to search, we didn't find it!
|
||||
if ( pat_first == pat_last ) return corpus_first; // empty pattern matches at start
|
||||
|
||||
const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last );
|
||||
// If the pattern is larger than the corpus, we can't find it!
|
||||
if ( k_corpus_length < k_pattern_length )
|
||||
return corpus_last;
|
||||
|
||||
// Do the search
|
||||
return this->do_search ( corpus_first, corpus_last );
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
typename boost::range_iterator<Range>::type operator () ( Range &r ) const {
|
||||
return (*this) (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
private:
|
||||
/// \cond DOXYGEN_HIDE
|
||||
patIter pat_first, pat_last;
|
||||
const difference_type k_pattern_length;
|
||||
typename traits::skip_table_t skip_;
|
||||
std::vector <difference_type> suffix_;
|
||||
|
||||
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
|
||||
/// \brief Searches the corpus for the pattern that was passed into the constructor
|
||||
///
|
||||
/// \param corpus_first The start of the data to search (Random Access Iterator)
|
||||
/// \param corpus_last One past the end of the data to search
|
||||
/// \param p A predicate used for the search comparisons.
|
||||
///
|
||||
template <typename corpusIter>
|
||||
corpusIter do_search ( corpusIter corpus_first, corpusIter corpus_last ) const {
|
||||
/* ---- Do the matching ---- */
|
||||
corpusIter curPos = corpus_first;
|
||||
const corpusIter lastPos = corpus_last - k_pattern_length;
|
||||
difference_type j, k, m;
|
||||
|
||||
while ( curPos <= lastPos ) {
|
||||
/* while ( std::distance ( curPos, corpus_last ) >= k_pattern_length ) { */
|
||||
// Do we match right where we are?
|
||||
j = k_pattern_length;
|
||||
while ( pat_first [j-1] == curPos [j-1] ) {
|
||||
j--;
|
||||
// We matched - we're done!
|
||||
if ( j == 0 )
|
||||
return curPos;
|
||||
}
|
||||
|
||||
// Since we didn't match, figure out how far to skip forward
|
||||
k = skip_ [ curPos [ j - 1 ]];
|
||||
m = j - k - 1;
|
||||
if ( k < j && m > suffix_ [ j ] )
|
||||
curPos += m;
|
||||
else
|
||||
curPos += suffix_ [ j ];
|
||||
}
|
||||
|
||||
return corpus_last; // We didn't find anything
|
||||
}
|
||||
|
||||
|
||||
void build_skip_table ( patIter first, patIter last ) {
|
||||
for ( std::size_t i = 0; first != last; ++first, ++i )
|
||||
skip_.insert ( *first, i );
|
||||
}
|
||||
|
||||
|
||||
template<typename Iter, typename Container>
|
||||
void compute_bm_prefix ( Iter pat_first, Iter pat_last, Container &prefix ) {
|
||||
const std::size_t count = std::distance ( pat_first, pat_last );
|
||||
BOOST_ASSERT ( count > 0 );
|
||||
BOOST_ASSERT ( prefix.size () == count );
|
||||
|
||||
prefix[0] = 0;
|
||||
std::size_t k = 0;
|
||||
for ( std::size_t i = 1; i < count; ++i ) {
|
||||
BOOST_ASSERT ( k < count );
|
||||
while ( k > 0 && ( pat_first[k] != pat_first[i] )) {
|
||||
BOOST_ASSERT ( k < count );
|
||||
k = prefix [ k - 1 ];
|
||||
}
|
||||
|
||||
if ( pat_first[k] == pat_first[i] )
|
||||
k++;
|
||||
prefix [ i ] = k;
|
||||
}
|
||||
}
|
||||
|
||||
void build_suffix_table ( patIter pat_first, patIter pat_last ) {
|
||||
const std::size_t count = (std::size_t) std::distance ( pat_first, pat_last );
|
||||
|
||||
if ( count > 0 ) { // empty pattern
|
||||
std::vector<typename std::iterator_traits<patIter>::value_type> reversed(count);
|
||||
(void) std::reverse_copy ( pat_first, pat_last, reversed.begin ());
|
||||
|
||||
std::vector<difference_type> prefix (count);
|
||||
compute_bm_prefix ( pat_first, pat_last, prefix );
|
||||
|
||||
std::vector<difference_type> prefix_reversed (count);
|
||||
compute_bm_prefix ( reversed.begin (), reversed.end (), prefix_reversed );
|
||||
|
||||
for ( std::size_t i = 0; i <= count; i++ )
|
||||
suffix_[i] = count - prefix [count-1];
|
||||
|
||||
for ( std::size_t i = 0; i < count; i++ ) {
|
||||
const std::size_t j = count - prefix_reversed[i];
|
||||
const difference_type k = i - prefix_reversed[i] + 1;
|
||||
|
||||
if (suffix_[j] > k)
|
||||
suffix_[j] = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// \endcond
|
||||
};
|
||||
|
||||
|
||||
/* Two ranges as inputs gives us four possibilities; with 2,3,3,4 parameters
|
||||
Use a bit of TMP to disambiguate the 3-argument templates */
|
||||
|
||||
/// \fn boyer_moore_search ( corpusIter corpus_first, corpusIter corpus_last,
|
||||
/// patIter pat_first, patIter pat_last )
|
||||
/// \brief Searches the corpus for the pattern.
|
||||
///
|
||||
/// \param corpus_first The start of the data to search (Random Access Iterator)
|
||||
/// \param corpus_last One past the end of the data to search
|
||||
/// \param pat_first The start of the pattern to search for (Random Access Iterator)
|
||||
/// \param pat_last One past the end of the data to search for
|
||||
///
|
||||
template <typename patIter, typename corpusIter>
|
||||
corpusIter boyer_moore_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last,
|
||||
patIter pat_first, patIter pat_last )
|
||||
{
|
||||
boyer_moore<patIter> bm ( pat_first, pat_last );
|
||||
return bm ( corpus_first, corpus_last );
|
||||
}
|
||||
|
||||
template <typename PatternRange, typename corpusIter>
|
||||
corpusIter boyer_moore_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
|
||||
return bm ( corpus_first, corpus_last );
|
||||
}
|
||||
|
||||
template <typename patIter, typename CorpusRange>
|
||||
typename boost::lazy_disable_if_c<
|
||||
boost::is_same<CorpusRange, patIter>::value, typename boost::range_iterator<CorpusRange> >
|
||||
::type
|
||||
boyer_moore_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last )
|
||||
{
|
||||
boyer_moore<patIter> bm ( pat_first, pat_last );
|
||||
return bm (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
||||
template <typename PatternRange, typename CorpusRange>
|
||||
typename boost::range_iterator<CorpusRange>::type
|
||||
boyer_moore_search ( CorpusRange &corpus, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
boyer_moore<pattern_iterator> bm ( boost::begin(pattern), boost::end (pattern));
|
||||
return bm (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
||||
|
||||
// Creator functions -- take a pattern range, return an object
|
||||
template <typename Range>
|
||||
boost::algorithm::boyer_moore<typename boost::range_iterator<const Range>::type>
|
||||
make_boyer_moore ( const Range &r ) {
|
||||
return boost::algorithm::boyer_moore
|
||||
<typename boost::range_iterator<const Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
boost::algorithm::boyer_moore<typename boost::range_iterator<Range>::type>
|
||||
make_boyer_moore ( Range &r ) {
|
||||
return boost::algorithm::boyer_moore
|
||||
<typename boost::range_iterator<Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_BOYER_MOORE_SEARCH_HPP
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2010-2012.
|
||||
|
||||
Distributed under the 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_ALGORITHM_BOYER_MOORE_HORSPOOOL_SEARCH_HPP
|
||||
#define BOOST_ALGORITHM_BOYER_MOORE_HORSPOOOL_SEARCH_HPP
|
||||
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/algorithm/searching/detail/bm_traits.hpp>
|
||||
#include <boost/algorithm/searching/detail/debugging.hpp>
|
||||
|
||||
// #define BOOST_ALGORITHM_BOYER_MOORE_HORSPOOL_DEBUG_HPP
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
/*
|
||||
A templated version of the boyer-moore-horspool searching algorithm.
|
||||
|
||||
Requirements:
|
||||
* Random access iterators
|
||||
* The two iterator types (patIter and corpusIter) must
|
||||
"point to" the same underlying type.
|
||||
* Additional requirements may be imposed buy the skip table, such as:
|
||||
** Numeric type (array-based skip table)
|
||||
** Hashable type (map-based skip table)
|
||||
|
||||
http://www-igm.univ-mlv.fr/%7Elecroq/string/node18.html
|
||||
|
||||
*/
|
||||
|
||||
template <typename patIter, typename traits = detail::BM_traits<patIter> >
|
||||
class boyer_moore_horspool {
|
||||
typedef typename std::iterator_traits<patIter>::difference_type difference_type;
|
||||
public:
|
||||
boyer_moore_horspool ( patIter first, patIter last )
|
||||
: pat_first ( first ), pat_last ( last ),
|
||||
k_pattern_length ( std::distance ( pat_first, pat_last )),
|
||||
skip_ ( k_pattern_length, k_pattern_length ) {
|
||||
|
||||
// Build the skip table
|
||||
std::size_t i = 0;
|
||||
if ( first != last ) // empty pattern?
|
||||
for ( patIter iter = first; iter != last-1; ++iter, ++i )
|
||||
skip_.insert ( *iter, k_pattern_length - 1 - i );
|
||||
#ifdef BOOST_ALGORITHM_BOYER_MOORE_HORSPOOL_DEBUG_HPP
|
||||
skip_.PrintSkipTable ();
|
||||
#endif
|
||||
}
|
||||
|
||||
~boyer_moore_horspool () {}
|
||||
|
||||
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
|
||||
/// \brief Searches the corpus for the pattern that was passed into the constructor
|
||||
///
|
||||
/// \param corpus_first The start of the data to search (Random Access Iterator)
|
||||
/// \param corpus_last One past the end of the data to search
|
||||
/// \param p A predicate used for the search comparisons.
|
||||
///
|
||||
template <typename corpusIter>
|
||||
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ) const {
|
||||
BOOST_STATIC_ASSERT (( boost::is_same<
|
||||
typename std::iterator_traits<patIter>::value_type,
|
||||
typename std::iterator_traits<corpusIter>::value_type>::value ));
|
||||
|
||||
if ( corpus_first == corpus_last ) return corpus_last; // if nothing to search, we didn't find it!
|
||||
if ( pat_first == pat_last ) return corpus_first; // empty pattern matches at start
|
||||
|
||||
const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last );
|
||||
// If the pattern is larger than the corpus, we can't find it!
|
||||
if ( k_corpus_length < k_pattern_length )
|
||||
return corpus_last;
|
||||
|
||||
// Do the search
|
||||
return this->do_search ( corpus_first, corpus_last );
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
typename boost::range_iterator<Range>::type operator () ( Range &r ) const {
|
||||
return (*this) (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
private:
|
||||
/// \cond DOXYGEN_HIDE
|
||||
patIter pat_first, pat_last;
|
||||
const difference_type k_pattern_length;
|
||||
typename traits::skip_table_t skip_;
|
||||
|
||||
/// \fn do_search ( corpusIter corpus_first, corpusIter corpus_last )
|
||||
/// \brief Searches the corpus for the pattern that was passed into the constructor
|
||||
///
|
||||
/// \param corpus_first The start of the data to search (Random Access Iterator)
|
||||
/// \param corpus_last One past the end of the data to search
|
||||
/// \param k_corpus_length The length of the corpus to search
|
||||
///
|
||||
template <typename corpusIter>
|
||||
corpusIter do_search ( corpusIter corpus_first, corpusIter corpus_last ) const {
|
||||
corpusIter curPos = corpus_first;
|
||||
const corpusIter lastPos = corpus_last - k_pattern_length;
|
||||
while ( curPos <= lastPos ) {
|
||||
// Do we match right where we are?
|
||||
std::size_t j = k_pattern_length - 1;
|
||||
while ( pat_first [j] == curPos [j] ) {
|
||||
// We matched - we're done!
|
||||
if ( j == 0 )
|
||||
return curPos;
|
||||
j--;
|
||||
}
|
||||
|
||||
curPos += skip_ [ curPos [ k_pattern_length - 1 ]];
|
||||
}
|
||||
|
||||
return corpus_last;
|
||||
}
|
||||
// \endcond
|
||||
};
|
||||
|
||||
/* Two ranges as inputs gives us four possibilities; with 2,3,3,4 parameters
|
||||
Use a bit of TMP to disambiguate the 3-argument templates */
|
||||
|
||||
/// \fn boyer_moore_horspool_search ( corpusIter corpus_first, corpusIter corpus_last,
|
||||
/// patIter pat_first, patIter pat_last )
|
||||
/// \brief Searches the corpus for the pattern.
|
||||
///
|
||||
/// \param corpus_first The start of the data to search (Random Access Iterator)
|
||||
/// \param corpus_last One past the end of the data to search
|
||||
/// \param pat_first The start of the pattern to search for (Random Access Iterator)
|
||||
/// \param pat_last One past the end of the data to search for
|
||||
///
|
||||
template <typename patIter, typename corpusIter>
|
||||
corpusIter boyer_moore_horspool_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last,
|
||||
patIter pat_first, patIter pat_last )
|
||||
{
|
||||
boyer_moore_horspool<patIter> bmh ( pat_first, pat_last );
|
||||
return bmh ( corpus_first, corpus_last );
|
||||
}
|
||||
|
||||
template <typename PatternRange, typename corpusIter>
|
||||
corpusIter boyer_moore_horspool_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
boyer_moore_horspool<pattern_iterator> bmh ( boost::begin(pattern), boost::end (pattern));
|
||||
return bmh ( corpus_first, corpus_last );
|
||||
}
|
||||
|
||||
template <typename patIter, typename CorpusRange>
|
||||
typename boost::lazy_disable_if_c<
|
||||
boost::is_same<CorpusRange, patIter>::value, typename boost::range_iterator<CorpusRange> >
|
||||
::type
|
||||
boyer_moore_horspool_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last )
|
||||
{
|
||||
boyer_moore_horspool<patIter> bmh ( pat_first, pat_last );
|
||||
return bm (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
||||
template <typename PatternRange, typename CorpusRange>
|
||||
typename boost::range_iterator<CorpusRange>::type
|
||||
boyer_moore_horspool_search ( CorpusRange &corpus, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
boyer_moore_horspool<pattern_iterator> bmh ( boost::begin(pattern), boost::end (pattern));
|
||||
return bmh (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
||||
|
||||
// Creator functions -- take a pattern range, return an object
|
||||
template <typename Range>
|
||||
boost::algorithm::boyer_moore_horspool<typename boost::range_iterator<const Range>::type>
|
||||
make_boyer_moore_horspool ( const Range &r ) {
|
||||
return boost::algorithm::boyer_moore_horspool
|
||||
<typename boost::range_iterator<const Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
boost::algorithm::boyer_moore_horspool<typename boost::range_iterator<Range>::type>
|
||||
make_boyer_moore_horspool ( Range &r ) {
|
||||
return boost::algorithm::boyer_moore_horspool
|
||||
<typename boost::range_iterator<Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_BOYER_MOORE_HORSPOOOL_SEARCH_HPP
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2010-2012.
|
||||
|
||||
Distributed under the 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_ALGORITHM_SEARCH_DETAIL_BM_TRAITS_HPP
|
||||
#define BOOST_ALGORITHM_SEARCH_DETAIL_BM_TRAITS_HPP
|
||||
|
||||
#include <climits> // for CHAR_BIT
|
||||
#include <vector>
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/remove_pointer.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/tr1/tr1/unordered_map>
|
||||
|
||||
#include <boost/algorithm/searching/detail/debugging.hpp>
|
||||
|
||||
namespace boost { namespace algorithm { namespace detail {
|
||||
|
||||
//
|
||||
// Default implementations of the skip tables for B-M and B-M-H
|
||||
//
|
||||
template<typename key_type, typename value_type, bool /*useArray*/> class skip_table;
|
||||
|
||||
// General case for data searching other than bytes; use a map
|
||||
template<typename key_type, typename value_type>
|
||||
class skip_table<key_type, value_type, false> {
|
||||
private:
|
||||
typedef std::tr1::unordered_map<key_type, value_type> skip_map;
|
||||
const value_type k_default_value;
|
||||
skip_map skip_;
|
||||
|
||||
public:
|
||||
skip_table ( std::size_t patSize, value_type default_value )
|
||||
: k_default_value ( default_value ), skip_ ( patSize ) {}
|
||||
|
||||
void insert ( key_type key, value_type val ) {
|
||||
skip_ [ key ] = val; // Would skip_.insert (val) be better here?
|
||||
}
|
||||
|
||||
value_type operator [] ( key_type key ) const {
|
||||
typename skip_map::const_iterator it = skip_.find ( key );
|
||||
return it == skip_.end () ? k_default_value : it->second;
|
||||
}
|
||||
|
||||
void PrintSkipTable () const {
|
||||
std::cout << "BM(H) Skip Table <unordered_map>:" << std::endl;
|
||||
for ( typename skip_map::const_iterator it = skip_.begin (); it != skip_.end (); ++it )
|
||||
if ( it->second != k_default_value )
|
||||
std::cout << " " << it->first << ": " << it->second << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Special case small numeric values; use an array
|
||||
template<typename key_type, typename value_type>
|
||||
class skip_table<key_type, value_type, true> {
|
||||
private:
|
||||
typedef typename boost::make_unsigned<key_type>::type unsigned_key_type;
|
||||
typedef boost::array<value_type, 1U << (CHAR_BIT * sizeof(key_type))> skip_map;
|
||||
skip_map skip_;
|
||||
const value_type k_default_value;
|
||||
public:
|
||||
skip_table ( std::size_t patSize, value_type default_value ) : k_default_value ( default_value ) {
|
||||
std::fill_n ( skip_.begin(), skip_.size(), default_value );
|
||||
}
|
||||
|
||||
void insert ( key_type key, value_type val ) {
|
||||
skip_ [ static_cast<unsigned_key_type> ( key ) ] = val;
|
||||
}
|
||||
|
||||
value_type operator [] ( key_type key ) const {
|
||||
return skip_ [ static_cast<unsigned_key_type> ( key ) ];
|
||||
}
|
||||
|
||||
void PrintSkipTable () const {
|
||||
std::cout << "BM(H) Skip Table <boost:array>:" << std::endl;
|
||||
for ( typename skip_map::const_iterator it = skip_.begin (); it != skip_.end (); ++it )
|
||||
if ( *it != k_default_value )
|
||||
std::cout << " " << std::distance (skip_.begin (), it) << ": " << *it << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Iterator>
|
||||
struct BM_traits {
|
||||
typedef typename std::iterator_traits<Iterator>::difference_type value_type;
|
||||
typedef typename std::iterator_traits<Iterator>::value_type key_type;
|
||||
typedef boost::algorithm::detail::skip_table<key_type, value_type,
|
||||
boost::is_integral<key_type>::value && (sizeof(key_type)==1)> skip_table_t;
|
||||
};
|
||||
|
||||
}}} // namespaces
|
||||
|
||||
#endif // BOOST_ALGORITHM_SEARCH_DETAIL_BM_TRAITS_HPP
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2010-2012.
|
||||
|
||||
Distributed under the 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_ALGORITHM_SEARCH_DETAIL_DEBUG_HPP
|
||||
#define BOOST_ALGORITHM_SEARCH_DETAIL_DEBUG_HPP
|
||||
|
||||
#include <iostream>
|
||||
/// \cond DOXYGEN_HIDE
|
||||
|
||||
namespace boost { namespace algorithm { namespace detail {
|
||||
|
||||
// Debugging support
|
||||
template <typename Iter>
|
||||
void PrintTable ( Iter first, Iter last ) {
|
||||
std::cout << std::distance ( first, last ) << ": { ";
|
||||
for ( Iter iter = first; iter != last; ++iter )
|
||||
std::cout << *iter << " ";
|
||||
std::cout << "}" << std::endl;
|
||||
}
|
||||
|
||||
}}}
|
||||
/// \endcond
|
||||
|
||||
#endif // BOOST_ALGORITHM_SEARCH_DETAIL_DEBUG_HPP
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
Copyright (c) Marshall Clow 2010-2012.
|
||||
|
||||
Distributed under the 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_ALGORITHM_KNUTH_MORRIS_PRATT_SEARCH_HPP
|
||||
#define BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_SEARCH_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <iterator> // for std::iterator_traits
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/algorithm/searching/detail/debugging.hpp>
|
||||
|
||||
// #define BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_DEBUG
|
||||
|
||||
namespace boost { namespace algorithm {
|
||||
|
||||
// #define NEW_KMP
|
||||
|
||||
/*
|
||||
A templated version of the Knuth-Morris-Pratt searching algorithm.
|
||||
|
||||
Requirements:
|
||||
* Random-access iterators
|
||||
* The two iterator types (I1 and I2) must "point to" the same underlying type.
|
||||
|
||||
http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm
|
||||
http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm
|
||||
*/
|
||||
|
||||
template <typename patIter>
|
||||
class knuth_morris_pratt {
|
||||
typedef typename std::iterator_traits<patIter>::difference_type difference_type;
|
||||
public:
|
||||
knuth_morris_pratt ( patIter first, patIter last )
|
||||
: pat_first ( first ), pat_last ( last ),
|
||||
k_pattern_length ( std::distance ( pat_first, pat_last )),
|
||||
skip_ ( k_pattern_length + 1 ) {
|
||||
#ifdef NEW_KMP
|
||||
preKmp ( pat_first, pat_last );
|
||||
#else
|
||||
init_skip_table ( pat_first, pat_last );
|
||||
#endif
|
||||
#ifdef BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_DEBUG
|
||||
detail::PrintTable ( skip_.begin (), skip_.end ());
|
||||
#endif
|
||||
}
|
||||
|
||||
~knuth_morris_pratt () {}
|
||||
|
||||
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
|
||||
/// \brief Searches the corpus for the pattern that was passed into the constructor
|
||||
///
|
||||
/// \param corpus_first The start of the data to search (Random Access Iterator)
|
||||
/// \param corpus_last One past the end of the data to search
|
||||
/// \param p A predicate used for the search comparisons.
|
||||
///
|
||||
template <typename corpusIter>
|
||||
corpusIter operator () ( corpusIter corpus_first, corpusIter corpus_last ) const {
|
||||
BOOST_STATIC_ASSERT (( boost::is_same<
|
||||
typename std::iterator_traits<patIter>::value_type,
|
||||
typename std::iterator_traits<corpusIter>::value_type>::value ));
|
||||
if ( corpus_first == corpus_last ) return corpus_last; // if nothing to search, we didn't find it!
|
||||
if ( pat_first == pat_last ) return corpus_first; // empty pattern matches at start
|
||||
|
||||
const difference_type k_corpus_length = std::distance ( corpus_first, corpus_last );
|
||||
// If the pattern is larger than the corpus, we can't find it!
|
||||
if ( k_corpus_length < k_pattern_length )
|
||||
return corpus_last;
|
||||
|
||||
return do_search ( corpus_first, corpus_last, k_corpus_length );
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
typename boost::range_iterator<Range>::type operator () ( Range &r ) const {
|
||||
return (*this) (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
private:
|
||||
/// \cond DOXYGEN_HIDE
|
||||
patIter pat_first, pat_last;
|
||||
const difference_type k_pattern_length;
|
||||
std::vector <difference_type> skip_;
|
||||
|
||||
/// \fn operator ( corpusIter corpus_first, corpusIter corpus_last, Pred p )
|
||||
/// \brief Searches the corpus for the pattern that was passed into the constructor
|
||||
///
|
||||
/// \param corpus_first The start of the data to search (Random Access Iterator)
|
||||
/// \param corpus_last One past the end of the data to search
|
||||
/// \param p A predicate used for the search comparisons.
|
||||
///
|
||||
template <typename corpusIter>
|
||||
corpusIter do_search ( corpusIter corpus_first, corpusIter corpus_last,
|
||||
difference_type k_corpus_length ) const {
|
||||
difference_type match_start = 0; // position in the corpus that we're matching
|
||||
|
||||
#ifdef NEW_KMP
|
||||
int patternIdx = 0;
|
||||
while ( match_start < k_corpus_length ) {
|
||||
while ( patternIdx > -1 && pat_first[patternIdx] != corpus_first [match_start] )
|
||||
patternIdx = skip_ [patternIdx]; //<--- Shifting the pattern on mismatch
|
||||
|
||||
patternIdx++;
|
||||
match_start++; //<--- corpus is always increased by 1
|
||||
|
||||
if ( patternIdx >= (int) k_pattern_length )
|
||||
return corpus_first + match_start - patternIdx;
|
||||
}
|
||||
|
||||
#else
|
||||
// At this point, we know:
|
||||
// k_pattern_length <= k_corpus_length
|
||||
// for all elements of skip, it holds -1 .. k_pattern_length
|
||||
//
|
||||
// In the loop, we have the following invariants
|
||||
// idx is in the range 0 .. k_pattern_length
|
||||
// match_start is in the range 0 .. k_corpus_length - k_pattern_length + 1
|
||||
|
||||
const difference_type last_match = k_corpus_length - k_pattern_length;
|
||||
difference_type idx = 0; // position in the pattern we're comparing
|
||||
|
||||
while ( match_start <= last_match ) {
|
||||
while ( pat_first [ idx ] == corpus_first [ match_start + idx ] ) {
|
||||
if ( ++idx == k_pattern_length )
|
||||
return corpus_first + match_start;
|
||||
}
|
||||
// Figure out where to start searching again
|
||||
// assert ( idx - skip_ [ idx ] > 0 ); // we're always moving forward
|
||||
match_start += idx - skip_ [ idx ];
|
||||
idx = skip_ [ idx ] >= 0 ? skip_ [ idx ] : 0;
|
||||
// assert ( idx >= 0 && idx < k_pattern_length );
|
||||
}
|
||||
#endif
|
||||
|
||||
// We didn't find anything
|
||||
return corpus_last;
|
||||
}
|
||||
|
||||
|
||||
void preKmp ( patIter first, patIter last ) {
|
||||
const /*std::size_t*/ int count = std::distance ( first, last );
|
||||
|
||||
int i, j;
|
||||
|
||||
i = 0;
|
||||
j = skip_[0] = -1;
|
||||
while (i < count) {
|
||||
while (j > -1 && first[i] != first[j])
|
||||
j = skip_[j];
|
||||
i++;
|
||||
j++;
|
||||
if (first[i] == first[j])
|
||||
skip_[i] = skip_[j];
|
||||
else
|
||||
skip_[i] = j;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void init_skip_table ( patIter first, patIter last ) {
|
||||
const difference_type count = std::distance ( first, last );
|
||||
|
||||
int j;
|
||||
skip_ [ 0 ] = -1;
|
||||
for ( int i = 1; i <= count; ++i ) {
|
||||
j = skip_ [ i - 1 ];
|
||||
while ( j >= 0 ) {
|
||||
if ( first [ j ] == first [ i - 1 ] )
|
||||
break;
|
||||
j = skip_ [ j ];
|
||||
}
|
||||
skip_ [ i ] = j + 1;
|
||||
}
|
||||
}
|
||||
// \endcond
|
||||
};
|
||||
|
||||
|
||||
/* Two ranges as inputs gives us four possibilities; with 2,3,3,4 parameters
|
||||
Use a bit of TMP to disambiguate the 3-argument templates */
|
||||
|
||||
/// \fn knuth_morris_pratt_search ( corpusIter corpus_first, corpusIter corpus_last,
|
||||
/// patIter pat_first, patIter pat_last )
|
||||
/// \brief Searches the corpus for the pattern.
|
||||
///
|
||||
/// \param corpus_first The start of the data to search (Random Access Iterator)
|
||||
/// \param corpus_last One past the end of the data to search
|
||||
/// \param pat_first The start of the pattern to search for (Random Access Iterator)
|
||||
/// \param pat_last One past the end of the data to search for
|
||||
///
|
||||
template <typename patIter, typename corpusIter>
|
||||
corpusIter knuth_morris_pratt_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last,
|
||||
patIter pat_first, patIter pat_last )
|
||||
{
|
||||
knuth_morris_pratt<patIter> kmp ( pat_first, pat_last );
|
||||
return kmp ( corpus_first, corpus_last );
|
||||
}
|
||||
|
||||
template <typename PatternRange, typename corpusIter>
|
||||
corpusIter knuth_morris_pratt_search (
|
||||
corpusIter corpus_first, corpusIter corpus_last, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
knuth_morris_pratt<pattern_iterator> kmp ( boost::begin(pattern), boost::end (pattern));
|
||||
return kmp ( corpus_first, corpus_last );
|
||||
}
|
||||
|
||||
template <typename patIter, typename CorpusRange>
|
||||
typename boost::lazy_disable_if_c<
|
||||
boost::is_same<CorpusRange, patIter>::value, typename boost::range_iterator<CorpusRange> >
|
||||
::type
|
||||
knuth_morris_pratt_search ( CorpusRange &corpus, patIter pat_first, patIter pat_last )
|
||||
{
|
||||
knuth_morris_pratt<patIter> kmp ( pat_first, pat_last );
|
||||
return kmp (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
||||
template <typename PatternRange, typename CorpusRange>
|
||||
typename boost::range_iterator<CorpusRange>::type
|
||||
knuth_morris_pratt_search ( CorpusRange &corpus, const PatternRange &pattern )
|
||||
{
|
||||
typedef typename boost::range_iterator<const PatternRange>::type pattern_iterator;
|
||||
knuth_morris_pratt<pattern_iterator> kmp ( boost::begin(pattern), boost::end (pattern));
|
||||
return kmp (boost::begin (corpus), boost::end (corpus));
|
||||
}
|
||||
|
||||
|
||||
// Creator functions -- take a pattern range, return an object
|
||||
template <typename Range>
|
||||
boost::algorithm::knuth_morris_pratt<typename boost::range_iterator<const Range>::type>
|
||||
make_knuth_morris_pratt ( const Range &r ) {
|
||||
return boost::algorithm::knuth_morris_pratt
|
||||
<typename boost::range_iterator<const Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
|
||||
template <typename Range>
|
||||
boost::algorithm::knuth_morris_pratt<typename boost::range_iterator<Range>::type>
|
||||
make_knuth_morris_pratt ( Range &r ) {
|
||||
return boost::algorithm::knuth_morris_pratt
|
||||
<typename boost::range_iterator<Range>::type> (boost::begin(r), boost::end(r));
|
||||
}
|
||||
}}
|
||||
|
||||
#endif // BOOST_ALGORITHM_KNUTH_MORRIS_PRATT_SEARCH_HPP
|
||||
@@ -56,7 +56,7 @@ namespace boost {
|
||||
// Copy the beginning of the sequence
|
||||
Output = std::copy( ::boost::begin(Input), ::boost::begin(M), Output );
|
||||
// Format find result
|
||||
// Copy formated result
|
||||
// Copy formatted result
|
||||
Output = std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
|
||||
// Copy the rest of the sequence
|
||||
Output = std::copy( M.end(), ::boost::end(Input), Output );
|
||||
@@ -118,11 +118,11 @@ namespace boost {
|
||||
|
||||
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() );
|
||||
boost::algorithm::detail::insert( Output, ::boost::end(Output), ::boost::begin(Input), M.begin() );
|
||||
// Copy formatted result
|
||||
boost::algorithm::detail::insert( Output, ::boost::end(Output), M.format_result() );
|
||||
// Copy the rest of the sequence
|
||||
insert( Output, ::boost::end(Output), M.end(), ::boost::end(Input) );
|
||||
boost::algorithm::detail::insert( Output, ::boost::end(Output), M.end(), ::boost::end(Input) );
|
||||
|
||||
return Output;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace boost {
|
||||
{
|
||||
// Copy the beginning of the sequence
|
||||
Output = std::copy( LastMatch, M.begin(), Output );
|
||||
// Copy formated result
|
||||
// Copy formatted result
|
||||
Output = std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output );
|
||||
|
||||
// Proceed to the next match
|
||||
@@ -134,9 +134,9 @@ namespace boost {
|
||||
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() );
|
||||
boost::algorithm::detail::insert( Output, ::boost::end(Output), LastMatch, M.begin() );
|
||||
// Copy formatted result
|
||||
boost::algorithm::detail::insert( Output, ::boost::end(Output), M.format_result() );
|
||||
|
||||
// Proceed to the next match
|
||||
LastMatch=M.end();
|
||||
@@ -218,7 +218,7 @@ namespace boost {
|
||||
// Adjust search iterator
|
||||
SearchIt=M.end();
|
||||
|
||||
// Copy formated replace to the storage
|
||||
// Copy formatted replace to the storage
|
||||
::boost::algorithm::detail::copy_to_storage( Storage, M.format_result() );
|
||||
|
||||
// Find range for a next match
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace boost {
|
||||
|
||||
// find last functor -----------------------------------------------//
|
||||
|
||||
// find the last match a subseqeunce in the sequence ( functor )
|
||||
// find the last match a subsequence in the sequence ( functor )
|
||||
/*
|
||||
Returns a pair <begin,end> marking the subsequence in the sequence.
|
||||
If the find fails, returns <End,End>
|
||||
|
||||
@@ -60,14 +60,14 @@ namespace boost {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Match result retrival
|
||||
// Match result retrieval
|
||||
const match_results_type& match_results() const
|
||||
{
|
||||
return m_MatchResults;
|
||||
}
|
||||
|
||||
private:
|
||||
// Saved matchresult
|
||||
// Saved match result
|
||||
match_results_type m_MatchResults;
|
||||
};
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace boost {
|
||||
|
||||
//! Find first algorithm ( case insensitive )
|
||||
/*!
|
||||
Search for the first occurence of the substring in the input.
|
||||
Search for the first occurrence of the substring in the input.
|
||||
Searching is case insensitive.
|
||||
|
||||
\param Input A string which will be searched.
|
||||
@@ -228,13 +228,13 @@ namespace boost {
|
||||
//! 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
|
||||
given size. If the input is shorter then required, whole input is 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.
|
||||
For N<0, at most size(Input)-|N| characters are extracted.
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c Range1T::iterator or
|
||||
@@ -258,13 +258,13 @@ namespace boost {
|
||||
//! Find tail algorithm
|
||||
/*!
|
||||
Get the tail of the input. Tail is a suffix of the string of the
|
||||
given size. If the input is shorter then required, whole input if considered
|
||||
given size. If the input is shorter then required, whole input is 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.
|
||||
For N<0, at most size(Input)-|N| characters are extracted.
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
Returned iterator is either \c RangeT::iterator or
|
||||
@@ -293,7 +293,7 @@ namespace boost {
|
||||
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 Pred A unary predicate to identify a token
|
||||
\param eCompress Enable/Disable compressing of adjacent tokens
|
||||
\return
|
||||
An \c iterator_range delimiting the match.
|
||||
|
||||
@@ -132,7 +132,10 @@ namespace boost {
|
||||
// increment
|
||||
void increment()
|
||||
{
|
||||
m_Match=this->do_find(m_Match.end(),m_End);
|
||||
if(m_Match.begin() == m_Match.end())
|
||||
m_Match=this->do_find(m_Match.end(),m_End);
|
||||
else
|
||||
m_Match=this->do_find(m_Match.begin()+1,m_End);
|
||||
}
|
||||
|
||||
// comparison
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace boost {
|
||||
Constructs a \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
|
||||
\param Format A predefined value used as a result for formatting
|
||||
\return An instance of the \c const_formatter object.
|
||||
*/
|
||||
template<typename RangeT>
|
||||
@@ -95,7 +95,7 @@ namespace boost {
|
||||
to extract a portion of the formatted sequence. The first finder's match is returned
|
||||
as a result
|
||||
|
||||
\param Finder a finder used to select a portion of the formated sequence
|
||||
\param Finder a finder used to select a portion of the formatted sequence
|
||||
\return An instance of the \c dissect_formatter object.
|
||||
*/
|
||||
template<typename FinderT>
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace boost {
|
||||
a match).
|
||||
\param Input A container which will be searched.
|
||||
\param Finder A Finder object used for searching
|
||||
\return A reference the result
|
||||
\return A reference to the result
|
||||
|
||||
\note Prior content of the result will be overwritten.
|
||||
*/
|
||||
@@ -122,7 +122,7 @@ namespace boost {
|
||||
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.
|
||||
\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
|
||||
@@ -131,7 +131,7 @@ namespace boost {
|
||||
a match).
|
||||
\param Input A container which will be searched.
|
||||
\param Finder A finder object used for searching
|
||||
\return A reference the result
|
||||
\return A reference to the result
|
||||
|
||||
\note Prior content of the result will be overwritten.
|
||||
*/
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
/*
|
||||
\file boost/algorith/string/predicate_facade.hpp
|
||||
This file containes predicate_facade definition. This template class is used
|
||||
This file contains predicate_facade definition. This template class is used
|
||||
to identify classification predicates, so they can be combined using
|
||||
composition operators.
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace boost {
|
||||
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
|
||||
of the iterator_range. In addition it contains match results
|
||||
from the \c regex_search algorithm.
|
||||
|
||||
\param Rx A regular expression
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace boost {
|
||||
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input range
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
\return
|
||||
An output iterator pointing just after the last inserted character or
|
||||
a copy of the input
|
||||
@@ -118,7 +118,7 @@ namespace boost {
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
*/
|
||||
template<typename SequenceT, typename PredicateT>
|
||||
inline void trim_left_if(SequenceT& Input, PredicateT IsSpace)
|
||||
@@ -158,7 +158,7 @@ namespace boost {
|
||||
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input range
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
\return
|
||||
An output iterator pointing just after the last inserted character or
|
||||
a copy of the input
|
||||
@@ -228,7 +228,7 @@ namespace boost {
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
*/
|
||||
template<typename SequenceT, typename PredicateT>
|
||||
inline void trim_right_if(SequenceT& Input, PredicateT IsSpace)
|
||||
@@ -270,7 +270,7 @@ namespace boost {
|
||||
|
||||
\param Output An output iterator to which the result will be copied
|
||||
\param Input An input range
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
\return
|
||||
An output iterator pointing just after the last inserted character or
|
||||
a copy of the input
|
||||
@@ -352,7 +352,7 @@ namespace boost {
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
*/
|
||||
template<typename SequenceT, typename PredicateT>
|
||||
inline void trim_if(SequenceT& Input, PredicateT IsSpace)
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace boost {
|
||||
The result is a trimmed copy of the input
|
||||
|
||||
\param Input An input sequence
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
\return A trimmed copy of the input
|
||||
*/
|
||||
template<typename SequenceT, typename PredicateT>
|
||||
@@ -70,7 +70,7 @@ namespace boost {
|
||||
The input sequence is modified in-place.
|
||||
|
||||
\param Input An input sequence
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
*/
|
||||
template<typename SequenceT, typename PredicateT>
|
||||
inline void trim_all_if(SequenceT& Input, PredicateT IsSpace)
|
||||
@@ -126,7 +126,7 @@ namespace boost {
|
||||
|
||||
\param Input An input sequence
|
||||
\param Fill A string used to fill the inner spaces
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
\return A trimmed copy of the input
|
||||
*/
|
||||
template<typename SequenceT, typename RangeT, typename PredicateT>
|
||||
@@ -149,7 +149,7 @@ namespace boost {
|
||||
|
||||
\param Input An input sequence
|
||||
\param Fill A string used to fill the inner spaces
|
||||
\param IsSpace An unary predicate identifying spaces
|
||||
\param IsSpace A unary predicate identifying spaces
|
||||
*/
|
||||
template<typename SequenceT, typename RangeT, typename PredicateT>
|
||||
inline void trim_fill_if(SequenceT& Input, const RangeT& Fill, PredicateT IsSpace)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
/*! \file
|
||||
Cumulative include for string_algo library.
|
||||
In addtion to string.hpp contains also regex-related stuff.
|
||||
In addition to string.hpp contains also regex-related stuff.
|
||||
*/
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
@@ -43,6 +43,8 @@ namespace archive {
|
||||
class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_exception :
|
||||
public virtual std::exception
|
||||
{
|
||||
protected:
|
||||
char m_buffer[128];
|
||||
public:
|
||||
typedef enum {
|
||||
no_exception, // initialized without code
|
||||
@@ -74,8 +76,6 @@ public:
|
||||
// type has been instantiated in more than one module.
|
||||
output_stream_error // error on input stream
|
||||
} exception_code;
|
||||
protected:
|
||||
std::string m_msg;
|
||||
public:
|
||||
exception_code code;
|
||||
archive_exception(
|
||||
@@ -83,9 +83,11 @@ public:
|
||||
const char * e1 = NULL,
|
||||
const char * e2 = NULL
|
||||
);
|
||||
~archive_exception() throw ();
|
||||
virtual const char *what( ) const throw();
|
||||
virtual ~archive_exception() throw();
|
||||
virtual const char *what() const throw();
|
||||
protected:
|
||||
unsigned int
|
||||
append(unsigned int l, const char * a);
|
||||
archive_exception();
|
||||
};
|
||||
|
||||
|
||||
@@ -150,7 +150,8 @@ private:
|
||||
base_type t;
|
||||
public:
|
||||
object_id_type(): t(0) {};
|
||||
explicit object_id_type(const unsigned int & t_) : t(t_){
|
||||
// note: presumes that size_t >= unsigned int.
|
||||
explicit object_id_type(const std::size_t & t_) : t(t_){
|
||||
BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max);
|
||||
}
|
||||
object_id_type(const object_id_type & t_) :
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <set>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/archive/detail/auto_link_archive.hpp>
|
||||
|
||||
#include <boost/archive/detail/abi_prefix.hpp> // must be the last header
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace std{
|
||||
|
||||
#define DONT_USE_HAS_NEW_OPERATOR ( \
|
||||
defined(__BORLANDC__) \
|
||||
|| defined(__IBMCPP__) \
|
||||
|| BOOST_WORKAROUND(__IBMCPP__, < 1210) \
|
||||
|| defined(BOOST_MSVC) && (BOOST_MSVC <= 1300) \
|
||||
|| defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590) \
|
||||
)
|
||||
|
||||
@@ -86,23 +86,21 @@ basic_text_iprimitive<IStream>::load_binary(
|
||||
,CharType
|
||||
>
|
||||
binary;
|
||||
|
||||
binary ti_begin = binary(
|
||||
|
||||
binary i = binary(
|
||||
BOOST_MAKE_PFTO_WRAPPER(
|
||||
iterators::istream_iterator<CharType>(is)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
char * caddr = static_cast<char *>(address);
|
||||
|
||||
// take care that we don't increment anymore than necessary
|
||||
while(--count > 0){
|
||||
*caddr++ = static_cast<char>(*ti_begin);
|
||||
++ti_begin;
|
||||
while(count-- > 0){
|
||||
*caddr++ = static_cast<char>(*i++);
|
||||
}
|
||||
*caddr++ = static_cast<char>(*ti_begin);
|
||||
|
||||
iterators::istream_iterator<CharType> i;
|
||||
|
||||
// skip over any excess input
|
||||
for(;;){
|
||||
BOOST_DEDUCED_TYPENAME IStream::int_type r;
|
||||
r = is.get();
|
||||
@@ -112,7 +110,7 @@ basic_text_iprimitive<IStream>::load_binary(
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class IStream>
|
||||
BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
|
||||
basic_text_iprimitive<IStream>::basic_text_iprimitive(
|
||||
|
||||
@@ -51,7 +51,7 @@ basic_text_oprimitive<OStream>::save_binary(
|
||||
8
|
||||
>
|
||||
>
|
||||
,72
|
||||
,76
|
||||
,const char // cwpro8 needs this
|
||||
>
|
||||
base64_text;
|
||||
|
||||
@@ -43,7 +43,7 @@ struct to_6_bit {
|
||||
-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,
|
||||
52,53,54,55,56,57,58,59,60,61,-1,-1,-1, 0,-1,-1, // render '=' as 0
|
||||
-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,
|
||||
|
||||
@@ -42,8 +42,8 @@ private:
|
||||
> super_t;
|
||||
|
||||
typedef head_iterator<Predicate, Base> this_t;
|
||||
typedef BOOST_DEDUCED_TYPENAME super_t::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME super_t::reference reference_type;
|
||||
typedef super_t::value_type value_type;
|
||||
typedef super_t::reference reference_type;
|
||||
|
||||
reference_type dereference_impl(){
|
||||
if(! m_end){
|
||||
|
||||
@@ -49,16 +49,17 @@ class istream_iterator :
|
||||
> super_t;
|
||||
typedef BOOST_DEDUCED_TYPENAME std::basic_istream<Elem> 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;
|
||||
}
|
||||
|
||||
/*
|
||||
//Access the value referred to
|
||||
Elem dereference() const {
|
||||
return m_current_value;
|
||||
}
|
||||
|
||||
void increment(){
|
||||
if(NULL != m_istream){
|
||||
m_current_value = static_cast<Elem>(m_istream->get());
|
||||
@@ -67,6 +68,17 @@ class istream_iterator :
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
//Access the value referred to
|
||||
Elem dereference() const {
|
||||
return m_istream->peek();
|
||||
}
|
||||
|
||||
void increment(){
|
||||
if(NULL != m_istream){
|
||||
m_istream->ignore(1);
|
||||
}
|
||||
}
|
||||
|
||||
istream_type *m_istream;
|
||||
Elem m_current_value;
|
||||
@@ -74,7 +86,7 @@ public:
|
||||
istream_iterator(istream_type & is) :
|
||||
m_istream(& is)
|
||||
{
|
||||
increment();
|
||||
//increment();
|
||||
}
|
||||
|
||||
istream_iterator() :
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/iterator/filter_iterator.hpp>
|
||||
#include <boost/iterator/iterator_traits.hpp>
|
||||
|
||||
//#include <boost/detail/workaround.hpp>
|
||||
//#if ! BOOST_WORKAROUND(BOOST_MSVC, <=1300)
|
||||
@@ -140,13 +141,19 @@ public:
|
||||
template<class Base>
|
||||
class remove_whitespace :
|
||||
public filter_iterator<
|
||||
remove_whitespace_predicate<BOOST_DEDUCED_TYPENAME Base::value_type>,
|
||||
remove_whitespace_predicate<
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type
|
||||
//BOOST_DEDUCED_TYPENAME Base::value_type
|
||||
>,
|
||||
Base
|
||||
>
|
||||
{
|
||||
friend class boost::iterator_core_access;
|
||||
typedef filter_iterator<
|
||||
remove_whitespace_predicate<BOOST_DEDUCED_TYPENAME Base::value_type>,
|
||||
remove_whitespace_predicate<
|
||||
BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type
|
||||
//BOOST_DEDUCED_TYPENAME Base::value_type
|
||||
>,
|
||||
Base
|
||||
> super_t;
|
||||
public:
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
// character and 8 bit bytes. Lowest common multiple is 24 => 4 6 bit characters
|
||||
// or 3 8 bit characters
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME & PTFO
|
||||
#include <boost/serialization/pfto.hpp>
|
||||
|
||||
@@ -66,101 +64,105 @@ class transform_width :
|
||||
typedef transform_width<Base, BitsOut, BitsIn, CharType> this_t;
|
||||
typedef BOOST_DEDUCED_TYPENAME iterator_value<Base>::type base_value_type;
|
||||
|
||||
CharType fill();
|
||||
|
||||
CharType dereference_impl(){
|
||||
if(! m_full){
|
||||
m_current_value = fill();
|
||||
m_full = true;
|
||||
}
|
||||
return m_current_value;
|
||||
}
|
||||
void fill();
|
||||
|
||||
CharType dereference() const {
|
||||
return const_cast<this_t *>(this)->dereference_impl();
|
||||
if(!m_buffer_out_full)
|
||||
const_cast<this_t *>(this)->fill();
|
||||
return m_buffer_out;
|
||||
}
|
||||
|
||||
// test for iterator equality
|
||||
bool equal_impl(const this_t & rhs){
|
||||
if(BitsIn < BitsOut) // discard any left over bits
|
||||
return this->base_reference() == rhs.base_reference();
|
||||
else{
|
||||
// BitsIn > BitsOut // zero fill
|
||||
if(this->base_reference() == rhs.base_reference()){
|
||||
m_end_of_sequence = true;
|
||||
return 0 == m_remaining_bits;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// standard iterator interface
|
||||
bool equal(const this_t & rhs) const {
|
||||
return
|
||||
this->base_reference() == rhs.base_reference();
|
||||
;
|
||||
return const_cast<this_t *>(this)->equal_impl(rhs);
|
||||
}
|
||||
|
||||
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;
|
||||
m_buffer_out_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;
|
||||
bool m_buffer_out_full;
|
||||
CharType m_buffer_out;
|
||||
|
||||
// last read element from input
|
||||
base_value_type m_buffer_in;
|
||||
|
||||
// number of bits to left in the input buffer.
|
||||
unsigned int m_remaining_bits;
|
||||
|
||||
// flag to indicate we've reached end of data.
|
||||
bool m_end_of_sequence;
|
||||
|
||||
public:
|
||||
// make composible buy using templated constructor
|
||||
template<class T>
|
||||
transform_width(BOOST_PFTO_WRAPPER(T) start) :
|
||||
super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))),
|
||||
m_displacement(0),
|
||||
m_full(false),
|
||||
m_bufferfull(false)
|
||||
m_buffer_out_full(false),
|
||||
m_remaining_bits(0),
|
||||
m_end_of_sequence(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)
|
||||
m_buffer_out_full(rhs.m_buffer_out_full),
|
||||
m_remaining_bits(rhs.m_remaining_bits),
|
||||
m_buffer_in(rhs.m_buffer_in),
|
||||
m_end_of_sequence(false)
|
||||
{}
|
||||
};
|
||||
|
||||
template<class Base, int BitsOut, int BitsIn, class CharType>
|
||||
CharType transform_width<Base, BitsOut, BitsIn, CharType>::fill(){
|
||||
CharType retval = 0;
|
||||
template<
|
||||
class Base,
|
||||
int BitsOut,
|
||||
int BitsIn,
|
||||
class CharType
|
||||
>
|
||||
void transform_width<Base, BitsOut, BitsIn, CharType>::fill() {
|
||||
unsigned int missing_bits = BitsOut;
|
||||
for(;;){
|
||||
unsigned int bcount;
|
||||
if(! m_bufferfull){
|
||||
m_buffer = * this->base_reference();
|
||||
m_bufferfull = true;
|
||||
bcount = BitsIn;
|
||||
m_buffer_out = 0;
|
||||
do{
|
||||
if(0 == m_remaining_bits){
|
||||
if(m_end_of_sequence){
|
||||
m_buffer_in = 0;
|
||||
m_remaining_bits = missing_bits;
|
||||
}
|
||||
else{
|
||||
m_buffer_in = * this->base_reference()++;
|
||||
m_remaining_bits = BitsIn;
|
||||
}
|
||||
}
|
||||
else
|
||||
bcount = BitsIn - m_displacement;
|
||||
unsigned int i = (std::min)(bcount, missing_bits);
|
||||
|
||||
// append these bits to the next output
|
||||
// up to the size of the output
|
||||
unsigned int i = std::min(missing_bits, m_remaining_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));
|
||||
base_value_type j = m_buffer_in >> (m_remaining_bits - i);
|
||||
// and mask off the un interesting higher bits
|
||||
// note presumption of twos complement notation
|
||||
j &= (1 << i) - 1;
|
||||
// append then interesting bits to the output value
|
||||
retval <<= i;
|
||||
retval |= j;
|
||||
m_buffer_out <<= i;
|
||||
m_buffer_out |= j;
|
||||
|
||||
// and update counters
|
||||
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;
|
||||
m_remaining_bits -= i;
|
||||
}while(0 < missing_bits);
|
||||
m_buffer_out_full = true;
|
||||
}
|
||||
|
||||
} // namespace iterators
|
||||
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
template<class T>
|
||||
struct non_polymorphic {
|
||||
static const boost::serialization::extended_type_info *
|
||||
get_object_identifier(T & t){
|
||||
get_object_identifier(T &){
|
||||
return & boost::serialization::singleton<
|
||||
BOOST_DEDUCED_TYPENAME
|
||||
boost::serialization::type_info_implementation< T >::type
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* 14 Apr 2012 - (mtc) Added support for boost::hash
|
||||
* 28 Dec 2010 - (mtc) Added cbegin and cend (and crbegin and crend) for C++Ox compatibility.
|
||||
* 10 Mar 2010 - (mtc) fill method added, matching resolution of the standard library working group.
|
||||
* See <http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#776> or Trac issue #3168
|
||||
@@ -46,6 +47,7 @@
|
||||
// Handles broken standard libraries better than <iterator>
|
||||
#include <boost/detail/iterator.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/functional/hash_fwd.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
// FIXES for broken compilers
|
||||
@@ -118,13 +120,13 @@ namespace boost {
|
||||
// operator[]
|
||||
reference operator[](size_type i)
|
||||
{
|
||||
BOOST_ASSERT( i < N && "out of range" );
|
||||
BOOST_ASSERT_MSG( i < N, "out of range" );
|
||||
return elems[i];
|
||||
}
|
||||
|
||||
const_reference operator[](size_type i) const
|
||||
{
|
||||
BOOST_ASSERT( i < N && "out of range" );
|
||||
BOOST_ASSERT_MSG( i < N, "out of range" );
|
||||
return elems[i];
|
||||
}
|
||||
|
||||
@@ -427,6 +429,13 @@ namespace boost {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template<class T, std::size_t N>
|
||||
std::size_t hash_value(const array<T,N>& arr)
|
||||
{
|
||||
return boost::hash_range(arr.begin(), arr.end());
|
||||
}
|
||||
|
||||
} /* namespace boost */
|
||||
|
||||
|
||||
|
||||
@@ -843,7 +843,7 @@ public:
|
||||
* ...
|
||||
* boost::asio::ip::tcp::socket::keep_alive option;
|
||||
* socket.get_option(option);
|
||||
* bool is_set = option.get();
|
||||
* bool is_set = option.value();
|
||||
* @endcode
|
||||
*/
|
||||
template <typename GettableSocketOption>
|
||||
@@ -891,7 +891,7 @@ public:
|
||||
* {
|
||||
* // An error occurred.
|
||||
* }
|
||||
* bool is_set = option.get();
|
||||
* bool is_set = option.value();
|
||||
* @endcode
|
||||
*/
|
||||
template <typename GettableSocketOption>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
basic_socket_streambuf<Protocol, StreamSocketService, \
|
||||
Time, TimeTraits, TimerService> >::member) \
|
||||
{ \
|
||||
tie(this); \
|
||||
this->setf(std::ios_base::unitbuf); \
|
||||
if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \
|
||||
this->setstate(std::ios_base::failbit); \
|
||||
} \
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
basic_socket_streambuf<Protocol, StreamSocketService,
|
||||
Time, TimeTraits, TimerService> >::member)
|
||||
{
|
||||
tie(this);
|
||||
this->setf(std::ios_base::unitbuf);
|
||||
}
|
||||
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
@@ -131,7 +131,7 @@ public:
|
||||
basic_socket_streambuf<Protocol, StreamSocketService,
|
||||
Time, TimeTraits, TimerService> >::member)
|
||||
{
|
||||
tie(this);
|
||||
this->setf(std::ios_base::unitbuf);
|
||||
if (rdbuf()->connect(x...) == 0)
|
||||
this->setstate(std::ios_base::failbit);
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
? bytes_avail : space_avail;
|
||||
storage_.resize(orig_size + length);
|
||||
std::size_t bytes_copied = boost::asio::buffer_copy(
|
||||
storage_.data(), buffers_, length);
|
||||
storage_.data() + orig_size, buffers_, length);
|
||||
|
||||
io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
/// Construct an iterator representing the beginning of the buffers' data.
|
||||
static buffers_iterator begin(const BufferSequence& buffers)
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 4) && BOOST_WORKAROUND(__GNUC_MINOR__, == 3)
|
||||
__attribute__ ((noinline))
|
||||
__attribute__ ((__noinline__))
|
||||
#endif
|
||||
{
|
||||
buffers_iterator new_iter;
|
||||
@@ -148,7 +148,7 @@ public:
|
||||
/// Construct an iterator representing the end of the buffers' data.
|
||||
static buffers_iterator end(const BufferSequence& buffers)
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 4) && BOOST_WORKAROUND(__GNUC_MINOR__, == 3)
|
||||
__attribute__ ((noinline))
|
||||
__attribute__ ((__noinline__))
|
||||
#endif
|
||||
{
|
||||
buffers_iterator new_iter;
|
||||
|
||||
@@ -31,10 +31,13 @@ namespace detail {
|
||||
|
||||
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
typedef long atomic_count;
|
||||
inline void increment(atomic_count& a, long b) { a += b; }
|
||||
#elif defined(BOOST_ASIO_HAS_STD_ATOMIC)
|
||||
typedef std::atomic<long> atomic_count;
|
||||
inline void increment(atomic_count& a, long b) { a += b; }
|
||||
#else // defined(BOOST_ASIO_HAS_STD_ATOMIC)
|
||||
typedef boost::detail::atomic_count atomic_count;
|
||||
inline void increment(atomic_count& a, long b) { while (b > 0) ++a, --b; }
|
||||
#endif // defined(BOOST_ASIO_HAS_STD_ATOMIC)
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -102,6 +102,13 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Obtain the value at the top of the stack.
|
||||
static Value* top()
|
||||
{
|
||||
context* elem = top_;
|
||||
return elem ? elem->value_ : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// The top of the stack of calls for the current thread.
|
||||
static tss_ptr<context> top_;
|
||||
|
||||
@@ -112,6 +112,22 @@
|
||||
# endif // defined(__GNUC__)
|
||||
#endif // !defined(BOOST_ASIO_DISABLE_STD_SYSTEM_ERROR)
|
||||
|
||||
// Compliant C++11 compilers put noexcept specifiers on error_category members.
|
||||
#if !defined(BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT)
|
||||
# if (BOOST_VERSION >= 105300)
|
||||
# define BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT BOOST_NOEXCEPT
|
||||
# elif defined(__GNUC__)
|
||||
# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
|
||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# define BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)
|
||||
# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
|
||||
# endif // defined(__GNUC__)
|
||||
# if !defined(BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT)
|
||||
# define BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT
|
||||
# endif // !defined(BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT)
|
||||
#endif // !defined(BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT)
|
||||
|
||||
// Standard library support for arrays.
|
||||
#if !defined(BOOST_ASIO_DISABLE_STD_ARRAY)
|
||||
# if defined(__GNUC__)
|
||||
@@ -163,7 +179,9 @@
|
||||
# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
|
||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# define BOOST_ASIO_HAS_STD_CHRONO
|
||||
# define BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK
|
||||
# if ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6))
|
||||
# define BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK
|
||||
# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6))
|
||||
# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
|
||||
# endif // defined(__GNUC__)
|
||||
@@ -355,4 +373,28 @@
|
||||
# endif // !defined(UNDER_CE)
|
||||
#endif // !defined(BOOST_ASIO_DISABLE_SIGNAL)
|
||||
|
||||
// Support for the __thread keyword extension.
|
||||
#if !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION)
|
||||
# if defined(__linux__)
|
||||
# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
# if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)
|
||||
# if !defined(__INTEL_COMPILER) && !defined(__ICL)
|
||||
# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1
|
||||
# elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100)
|
||||
# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1
|
||||
# endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100)
|
||||
# endif // ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)
|
||||
# endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
# endif // defined(__linux__)
|
||||
#endif // !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION)
|
||||
|
||||
// Support for POSIX ssize_t typedef.
|
||||
#if !defined(BOOST_ASIO_DISABLE_SSIZE_T)
|
||||
# if defined(__linux__) \
|
||||
|| (defined(__MACH__) && defined(__APPLE__))
|
||||
# define BOOST_ASIO_HAS_SSIZE_T 1
|
||||
# endif // defined(__linux__)
|
||||
// || (defined(__MACH__) && defined(__APPLE__))
|
||||
#endif // !defined(BOOST_ASIO_DISABLE_SSIZE_T)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_CONFIG_HPP
|
||||
|
||||
@@ -88,9 +88,9 @@ BOOST_ASIO_DECL bool non_blocking_write(int d,
|
||||
BOOST_ASIO_DECL int ioctl(int d, state_type& state, long cmd,
|
||||
ioctl_arg_type* arg, boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL int fcntl(int d, long cmd, boost::system::error_code& ec);
|
||||
BOOST_ASIO_DECL int fcntl(int d, int cmd, boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL int fcntl(int d, long cmd,
|
||||
BOOST_ASIO_DECL int fcntl(int d, int cmd,
|
||||
long arg, boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL int poll_read(int d,
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_EPOLL)
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/detail/atomic_count.hpp>
|
||||
@@ -59,6 +60,7 @@ public:
|
||||
mutex mutex_;
|
||||
epoll_reactor* reactor_;
|
||||
int descriptor_;
|
||||
boost::uint32_t registered_events_;
|
||||
op_queue<reactor_op> op_queue_[max_ops];
|
||||
bool shutdown_;
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
# include <boost/asio/detail/macos_fenced_block.hpp>
|
||||
#elif defined(__sun)
|
||||
# include <boost/asio/detail/solaris_fenced_block.hpp>
|
||||
#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__)
|
||||
#elif defined(__GNUC__) && defined(__arm__) \
|
||||
&& !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
# include <boost/asio/detail/gcc_arm_fenced_block.hpp>
|
||||
#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
|
||||
# include <boost/asio/detail/gcc_hppa_fenced_block.hpp>
|
||||
@@ -34,8 +35,7 @@
|
||||
#elif defined(__GNUC__) \
|
||||
&& ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
|
||||
&& !defined(__INTEL_COMPILER) && !defined(__ICL) \
|
||||
&& !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \
|
||||
&& !defined(ANDROID) && !defined(__ANDROID__)
|
||||
&& !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
|
||||
# include <boost/asio/detail/gcc_sync_fenced_block.hpp>
|
||||
#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
|
||||
# include <boost/asio/detail/win_fenced_block.hpp>
|
||||
@@ -55,7 +55,8 @@ typedef null_fenced_block fenced_block;
|
||||
typedef macos_fenced_block fenced_block;
|
||||
#elif defined(__sun)
|
||||
typedef solaris_fenced_block fenced_block;
|
||||
#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__)
|
||||
#elif defined(__GNUC__) && defined(__arm__) \
|
||||
&& !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
|
||||
typedef gcc_arm_fenced_block fenced_block;
|
||||
#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
|
||||
typedef gcc_hppa_fenced_block fenced_block;
|
||||
@@ -64,8 +65,7 @@ typedef gcc_x86_fenced_block fenced_block;
|
||||
#elif defined(__GNUC__) \
|
||||
&& ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
|
||||
&& !defined(__INTEL_COMPILER) && !defined(__ICL) \
|
||||
&& !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) \
|
||||
&& !defined(ANDROID) && !defined(__ANDROID__)
|
||||
&& !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
|
||||
typedef gcc_sync_fenced_block fenced_block;
|
||||
#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
|
||||
typedef win_fenced_block fenced_block;
|
||||
|
||||
@@ -40,17 +40,17 @@ public:
|
||||
// Constructor for a full fenced block.
|
||||
explicit gcc_x86_fenced_block(full_t)
|
||||
{
|
||||
barrier1();
|
||||
lbarrier();
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
~gcc_x86_fenced_block()
|
||||
{
|
||||
barrier2();
|
||||
sbarrier();
|
||||
}
|
||||
|
||||
private:
|
||||
static int barrier1()
|
||||
static int barrier()
|
||||
{
|
||||
int r = 0, m = 1;
|
||||
__asm__ __volatile__ (
|
||||
@@ -61,12 +61,21 @@ private:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void barrier2()
|
||||
static void lbarrier()
|
||||
{
|
||||
#if defined(__SSE2__)
|
||||
__asm__ __volatile__ ("mfence" ::: "memory");
|
||||
__asm__ __volatile__ ("lfence" ::: "memory");
|
||||
#else // defined(__SSE2__)
|
||||
barrier1();
|
||||
barrier();
|
||||
#endif // defined(__SSE2__)
|
||||
}
|
||||
|
||||
static void sbarrier()
|
||||
{
|
||||
#if defined(__SSE2__)
|
||||
__asm__ __volatile__ ("sfence" ::: "memory");
|
||||
#else // defined(__SSE2__)
|
||||
barrier();
|
||||
#endif // defined(__SSE2__)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -183,7 +183,8 @@ std::size_t sync_read(int d, state_type state, buf* bufs,
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
errno = 0;
|
||||
int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
|
||||
signed_size_type bytes = error_wrapper(::readv(
|
||||
d, bufs, static_cast<int>(count)), ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
@@ -215,7 +216,8 @@ bool non_blocking_read(int d, buf* bufs, std::size_t count,
|
||||
{
|
||||
// Read some data.
|
||||
errno = 0;
|
||||
int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
|
||||
signed_size_type bytes = error_wrapper(::readv(
|
||||
d, bufs, static_cast<int>(count)), ec);
|
||||
|
||||
// Check for end of stream.
|
||||
if (bytes == 0)
|
||||
@@ -267,7 +269,8 @@ std::size_t sync_write(int d, state_type state, const buf* bufs,
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
errno = 0;
|
||||
int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
|
||||
signed_size_type bytes = error_wrapper(::writev(
|
||||
d, bufs, static_cast<int>(count)), ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
@@ -292,7 +295,8 @@ bool non_blocking_write(int d, const buf* bufs, std::size_t count,
|
||||
{
|
||||
// Write some data.
|
||||
errno = 0;
|
||||
int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
|
||||
signed_size_type bytes = error_wrapper(::writev(
|
||||
d, bufs, static_cast<int>(count)), ec);
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
@@ -357,7 +361,7 @@ int ioctl(int d, state_type& state, long cmd,
|
||||
return result;
|
||||
}
|
||||
|
||||
int fcntl(int d, long cmd, boost::system::error_code& ec)
|
||||
int fcntl(int d, int cmd, boost::system::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
@@ -372,7 +376,7 @@ int fcntl(int d, long cmd, boost::system::error_code& ec)
|
||||
return result;
|
||||
}
|
||||
|
||||
int fcntl(int d, long cmd, long arg, boost::system::error_code& ec)
|
||||
int fcntl(int d, int cmd, long arg, boost::system::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
|
||||
@@ -127,7 +127,7 @@ void epoll_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
|
||||
for (descriptor_state* state = registered_descriptors_.first();
|
||||
state != 0; state = state->next_)
|
||||
{
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
ev.events = state->registered_events_;
|
||||
ev.data.ptr = state;
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, state->descriptor_, &ev);
|
||||
if (result != 0)
|
||||
@@ -159,7 +159,8 @@ int epoll_reactor::register_descriptor(socket_type descriptor,
|
||||
}
|
||||
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;
|
||||
descriptor_data->registered_events_ = ev.events;
|
||||
ev.data.ptr = descriptor_data;
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
@@ -184,7 +185,8 @@ int epoll_reactor::register_internal_descriptor(
|
||||
}
|
||||
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;
|
||||
descriptor_data->registered_events_ = ev.events;
|
||||
ev.data.ptr = descriptor_data;
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
@@ -222,23 +224,47 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
|
||||
if (descriptor_data->op_queue_[op_type].empty())
|
||||
{
|
||||
if (allow_speculative)
|
||||
if (allow_speculative
|
||||
&& (op_type != read_op
|
||||
|| descriptor_data->op_queue_[except_op].empty()))
|
||||
{
|
||||
if (op_type != read_op || descriptor_data->op_queue_[except_op].empty())
|
||||
if (op->perform())
|
||||
{
|
||||
if (op->perform())
|
||||
descriptor_lock.unlock();
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
if (op_type == write_op)
|
||||
{
|
||||
if ((descriptor_data->registered_events_ & EPOLLOUT) == 0)
|
||||
{
|
||||
descriptor_lock.unlock();
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = descriptor_data->registered_events_ | EPOLLOUT;
|
||||
ev.data.ptr = descriptor_data;
|
||||
if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev) == 0)
|
||||
{
|
||||
descriptor_data->registered_events_ |= ev.events;
|
||||
}
|
||||
else
|
||||
{
|
||||
op->ec_ = boost::system::error_code(errno,
|
||||
boost::asio::error::get_system_category());
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (op_type == write_op)
|
||||
{
|
||||
descriptor_data->registered_events_ |= EPOLLOUT;
|
||||
}
|
||||
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP
|
||||
| EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
ev.events = descriptor_data->registered_events_;
|
||||
ev.data.ptr = descriptor_data;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
|
||||
}
|
||||
@@ -440,7 +466,7 @@ int epoll_reactor::do_epoll_create()
|
||||
errno = EINVAL;
|
||||
#endif // defined(EPOLL_CLOEXEC)
|
||||
|
||||
if (fd == -1 && errno == EINVAL)
|
||||
if (fd == -1 && (errno == EINVAL || errno == ENOSYS))
|
||||
{
|
||||
fd = epoll_create(epoll_size);
|
||||
if (fd != -1)
|
||||
|
||||
@@ -367,7 +367,7 @@ void kqueue_reactor::run(bool block, op_queue<operation>& ops)
|
||||
// Dispatch the waiting events.
|
||||
for (int i = 0; i < num_events; ++i)
|
||||
{
|
||||
int descriptor = events[i].ident;
|
||||
int descriptor = static_cast<int>(events[i].ident);
|
||||
void* ptr = reinterpret_cast<void*>(events[i].udata);
|
||||
if (ptr == &interrupter_)
|
||||
{
|
||||
@@ -397,7 +397,8 @@ void kqueue_reactor::run(bool block, op_queue<operation>& ops)
|
||||
{
|
||||
if (events[i].flags & EV_ERROR)
|
||||
{
|
||||
op->ec_ = boost::system::error_code(events[i].data,
|
||||
op->ec_ = boost::system::error_code(
|
||||
static_cast<int>(events[i].data),
|
||||
boost::asio::error::get_system_category());
|
||||
descriptor_data->op_queue_[j].pop();
|
||||
ops.push(op);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <boost/asio/detail/pipe_select_interrupter.hpp>
|
||||
#include <boost/asio/detail/socket_types.hpp>
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
|
||||
@@ -90,7 +91,7 @@ void pipe_select_interrupter::recreate()
|
||||
void pipe_select_interrupter::interrupt()
|
||||
{
|
||||
char byte = 0;
|
||||
int result = ::write(write_descriptor_, &byte, 1);
|
||||
signed_size_type result = ::write(write_descriptor_, &byte, 1);
|
||||
(void)result;
|
||||
}
|
||||
|
||||
@@ -99,7 +100,7 @@ bool pipe_select_interrupter::reset()
|
||||
for (;;)
|
||||
{
|
||||
char data[1024];
|
||||
int bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
signed_size_type bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
if (bytes_read < 0 && errno == EINTR)
|
||||
continue;
|
||||
bool was_interrupted = (bytes_read > 0);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <boost/asio/detail/posix_event.hpp>
|
||||
#include <boost/asio/detail/throw_error.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ void asio_signal_handler(int signal_number)
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
int saved_errno = errno;
|
||||
signal_state* state = get_signal_state();
|
||||
int result = ::write(state->write_descriptor_,
|
||||
signed_size_type result = ::write(state->write_descriptor_,
|
||||
&signal_number, sizeof(signal_number));
|
||||
(void)result;
|
||||
errno = saved_errno;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
@@ -669,8 +670,8 @@ inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
|
||||
name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
|
||||
}
|
||||
|
||||
int recv(socket_type s, buf* bufs, size_t count, int flags,
|
||||
boost::system::error_code& ec)
|
||||
signed_size_type recv(socket_type s, buf* bufs, size_t count,
|
||||
int flags, boost::system::error_code& ec)
|
||||
{
|
||||
clear_last_error();
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
@@ -691,8 +692,8 @@ int recv(socket_type s, buf* bufs, size_t count, int flags,
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
msg.msg_iov = bufs;
|
||||
msg.msg_iovlen = count;
|
||||
int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
|
||||
msg.msg_iovlen = static_cast<int>(count);
|
||||
signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
|
||||
if (result >= 0)
|
||||
ec = boost::system::error_code();
|
||||
return result;
|
||||
@@ -719,7 +720,7 @@ size_t sync_recv(socket_type s, state_type state, buf* bufs,
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
int bytes = socket_ops::recv(s, bufs, count, flags, ec);
|
||||
signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
@@ -781,7 +782,7 @@ bool non_blocking_recv(socket_type s,
|
||||
for (;;)
|
||||
{
|
||||
// Read some data.
|
||||
int bytes = socket_ops::recv(s, bufs, count, flags, ec);
|
||||
signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec);
|
||||
|
||||
// Check for end of stream.
|
||||
if (is_stream && bytes == 0)
|
||||
@@ -814,8 +815,8 @@ bool non_blocking_recv(socket_type s,
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
|
||||
socket_addr_type* addr, std::size_t* addrlen,
|
||||
signed_size_type 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_last_error();
|
||||
@@ -839,10 +840,10 @@ int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
init_msghdr_msg_name(msg.msg_name, addr);
|
||||
msg.msg_namelen = *addrlen;
|
||||
msg.msg_namelen = static_cast<int>(*addrlen);
|
||||
msg.msg_iov = bufs;
|
||||
msg.msg_iovlen = count;
|
||||
int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
|
||||
msg.msg_iovlen = static_cast<int>(count);
|
||||
signed_size_type result = error_wrapper(::recvmsg(s, &msg, flags), ec);
|
||||
*addrlen = msg.msg_namelen;
|
||||
if (result >= 0)
|
||||
ec = boost::system::error_code();
|
||||
@@ -864,7 +865,8 @@ size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
int bytes = socket_ops::recvfrom(s, bufs, count, flags, addr, addrlen, ec);
|
||||
signed_size_type bytes = socket_ops::recvfrom(
|
||||
s, bufs, count, flags, addr, addrlen, ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes >= 0)
|
||||
@@ -912,7 +914,8 @@ bool non_blocking_recvfrom(socket_type s,
|
||||
for (;;)
|
||||
{
|
||||
// Read some data.
|
||||
int bytes = socket_ops::recvfrom(s, bufs, count, flags, addr, addrlen, ec);
|
||||
signed_size_type bytes = socket_ops::recvfrom(
|
||||
s, bufs, count, flags, addr, addrlen, ec);
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
@@ -938,7 +941,7 @@ bool non_blocking_recvfrom(socket_type s,
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
int recvmsg(socket_type s, buf* bufs, size_t count,
|
||||
signed_size_type recvmsg(socket_type s, buf* bufs, size_t count,
|
||||
int in_flags, int& out_flags, boost::system::error_code& ec)
|
||||
{
|
||||
clear_last_error();
|
||||
@@ -948,8 +951,8 @@ int recvmsg(socket_type s, buf* bufs, size_t count,
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
msg.msg_iov = bufs;
|
||||
msg.msg_iovlen = count;
|
||||
int result = error_wrapper(::recvmsg(s, &msg, in_flags), ec);
|
||||
msg.msg_iovlen = static_cast<int>(count);
|
||||
signed_size_type result = error_wrapper(::recvmsg(s, &msg, in_flags), ec);
|
||||
if (result >= 0)
|
||||
{
|
||||
ec = boost::system::error_code();
|
||||
@@ -975,7 +978,8 @@ size_t sync_recvmsg(socket_type s, state_type state,
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
int bytes = socket_ops::recvmsg(s, bufs, count, in_flags, out_flags, ec);
|
||||
signed_size_type bytes = socket_ops::recvmsg(
|
||||
s, bufs, count, in_flags, out_flags, ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes >= 0)
|
||||
@@ -1022,7 +1026,8 @@ bool non_blocking_recvmsg(socket_type s,
|
||||
for (;;)
|
||||
{
|
||||
// Read some data.
|
||||
int bytes = socket_ops::recvmsg(s, bufs, count, in_flags, out_flags, ec);
|
||||
signed_size_type bytes = socket_ops::recvmsg(
|
||||
s, bufs, count, in_flags, out_flags, ec);
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
@@ -1048,8 +1053,8 @@ bool non_blocking_recvmsg(socket_type s,
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
int send(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
boost::system::error_code& ec)
|
||||
signed_size_type send(socket_type s, const buf* bufs, size_t count,
|
||||
int flags, boost::system::error_code& ec)
|
||||
{
|
||||
clear_last_error();
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
@@ -1070,11 +1075,11 @@ int send(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
msg.msg_iov = const_cast<buf*>(bufs);
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_iovlen = static_cast<int>(count);
|
||||
#if defined(__linux__)
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif // defined(__linux__)
|
||||
int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
|
||||
signed_size_type result = error_wrapper(::sendmsg(s, &msg, flags), ec);
|
||||
if (result >= 0)
|
||||
ec = boost::system::error_code();
|
||||
return result;
|
||||
@@ -1101,7 +1106,7 @@ size_t sync_send(socket_type s, state_type state, const buf* bufs,
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
int bytes = socket_ops::send(s, bufs, count, flags, ec);
|
||||
signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes >= 0)
|
||||
@@ -1148,7 +1153,7 @@ bool non_blocking_send(socket_type s,
|
||||
for (;;)
|
||||
{
|
||||
// Write some data.
|
||||
int bytes = socket_ops::send(s, bufs, count, flags, ec);
|
||||
signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec);
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
@@ -1174,8 +1179,8 @@ bool non_blocking_send(socket_type s,
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
int sendto(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
const socket_addr_type* addr, std::size_t addrlen,
|
||||
signed_size_type 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_last_error();
|
||||
@@ -1197,13 +1202,13 @@ int sendto(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
init_msghdr_msg_name(msg.msg_name, addr);
|
||||
msg.msg_namelen = addrlen;
|
||||
msg.msg_namelen = static_cast<int>(addrlen);
|
||||
msg.msg_iov = const_cast<buf*>(bufs);
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_iovlen = static_cast<int>(count);
|
||||
#if defined(__linux__)
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif // defined(__linux__)
|
||||
int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
|
||||
signed_size_type result = error_wrapper(::sendmsg(s, &msg, flags), ec);
|
||||
if (result >= 0)
|
||||
ec = boost::system::error_code();
|
||||
return result;
|
||||
@@ -1224,7 +1229,8 @@ size_t sync_sendto(socket_type s, state_type state, const buf* bufs,
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
int bytes = socket_ops::sendto(s, bufs, count, flags, addr, addrlen, ec);
|
||||
signed_size_type bytes = socket_ops::sendto(
|
||||
s, bufs, count, flags, addr, addrlen, ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes >= 0)
|
||||
@@ -1252,7 +1258,8 @@ bool non_blocking_sendto(socket_type s,
|
||||
for (;;)
|
||||
{
|
||||
// Write some data.
|
||||
int bytes = socket_ops::sendto(s, bufs, count, flags, addr, addrlen, ec);
|
||||
signed_size_type bytes = socket_ops::sendto(
|
||||
s, bufs, count, flags, addr, addrlen, ec);
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == boost::asio::error::interrupted)
|
||||
@@ -1867,7 +1874,8 @@ const char* inet_ntop(int af, const void* src, char* dest, size_t length,
|
||||
|
||||
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);
|
||||
const char* result = error_wrapper(::inet_ntop(
|
||||
af, src, dest, static_cast<int>(length)), ec);
|
||||
if (result == 0 && !ec)
|
||||
ec = boost::asio::error::invalid_argument;
|
||||
if (result != 0 && af == AF_INET6 && scope_id != 0)
|
||||
@@ -1877,7 +1885,8 @@ const char* inet_ntop(int af, const void* src, char* dest, size_t length,
|
||||
const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);
|
||||
bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe)
|
||||
&& ((ipv6_address->s6_addr[1] & 0xc0) == 0x80));
|
||||
if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)
|
||||
if (!is_link_local
|
||||
|| if_indextoname(static_cast<unsigned>(scope_id), if_name + 1) == 0)
|
||||
sprintf(if_name + 1, "%lu", scope_id);
|
||||
strcat(dest, if_name);
|
||||
}
|
||||
|
||||
@@ -50,11 +50,6 @@ struct strand_service::on_dispatch_exit
|
||||
}
|
||||
};
|
||||
|
||||
inline void strand_service::destroy(strand_service::implementation_type& impl)
|
||||
{
|
||||
impl = 0;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void strand_service::dispatch(strand_service::implementation_type& impl,
|
||||
Handler handler)
|
||||
|
||||
@@ -38,7 +38,7 @@ struct strand_service::on_do_complete_exit
|
||||
impl_->mutex_.unlock();
|
||||
|
||||
if (more_handlers)
|
||||
owner_->post_immediate_completion(impl_);
|
||||
owner_->post_private_immediate_completion(impl_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ void task_io_service::dispatch(Handler handler)
|
||||
|
||||
BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch"));
|
||||
|
||||
post_immediate_completion(p.p);
|
||||
post_non_private_immediate_completion(p.p);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <boost/asio/detail/event.hpp>
|
||||
#include <boost/asio/detail/reactor.hpp>
|
||||
#include <boost/asio/detail/task_io_service.hpp>
|
||||
#include <boost/asio/detail/task_io_service_thread_info.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
@@ -34,44 +35,55 @@ struct task_io_service::task_cleanup
|
||||
{
|
||||
~task_cleanup()
|
||||
{
|
||||
if (this_thread_->private_outstanding_work > 0)
|
||||
{
|
||||
boost::asio::detail::increment(
|
||||
task_io_service_->outstanding_work_,
|
||||
this_thread_->private_outstanding_work);
|
||||
}
|
||||
this_thread_->private_outstanding_work = 0;
|
||||
|
||||
// Enqueue the completed operations and reinsert the task at the end of
|
||||
// the operation queue.
|
||||
lock_->lock();
|
||||
task_io_service_->task_interrupted_ = true;
|
||||
task_io_service_->op_queue_.push(*ops_);
|
||||
task_io_service_->op_queue_.push(this_thread_->private_op_queue);
|
||||
task_io_service_->op_queue_.push(&task_io_service_->task_operation_);
|
||||
}
|
||||
|
||||
task_io_service* task_io_service_;
|
||||
mutex::scoped_lock* lock_;
|
||||
op_queue<operation>* ops_;
|
||||
thread_info* this_thread_;
|
||||
};
|
||||
|
||||
struct task_io_service::work_cleanup
|
||||
{
|
||||
~work_cleanup()
|
||||
{
|
||||
task_io_service_->work_finished();
|
||||
if (this_thread_->private_outstanding_work > 1)
|
||||
{
|
||||
boost::asio::detail::increment(
|
||||
task_io_service_->outstanding_work_,
|
||||
this_thread_->private_outstanding_work - 1);
|
||||
}
|
||||
else if (this_thread_->private_outstanding_work < 1)
|
||||
{
|
||||
task_io_service_->work_finished();
|
||||
}
|
||||
this_thread_->private_outstanding_work = 0;
|
||||
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
if (!ops_->empty())
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
if (!this_thread_->private_op_queue.empty())
|
||||
{
|
||||
lock_->lock();
|
||||
task_io_service_->op_queue_.push(*ops_);
|
||||
task_io_service_->op_queue_.push(this_thread_->private_op_queue);
|
||||
}
|
||||
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
}
|
||||
|
||||
task_io_service* task_io_service_;
|
||||
mutex::scoped_lock* lock_;
|
||||
op_queue<operation>* ops_;
|
||||
};
|
||||
|
||||
struct task_io_service::thread_info
|
||||
{
|
||||
event* wakeup_event;
|
||||
op_queue<operation>* private_op_queue;
|
||||
thread_info* next;
|
||||
thread_info* this_thread_;
|
||||
};
|
||||
|
||||
task_io_service::task_io_service(
|
||||
@@ -131,19 +143,14 @@ std::size_t task_io_service::run(boost::system::error_code& ec)
|
||||
thread_info this_thread;
|
||||
event wakeup_event;
|
||||
this_thread.wakeup_event = &wakeup_event;
|
||||
op_queue<operation> private_op_queue;
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
this_thread.private_op_queue = one_thread_ == 1 ? &private_op_queue : 0;
|
||||
#else // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
this_thread.private_op_queue = 0;
|
||||
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
this_thread.private_outstanding_work = 0;
|
||||
this_thread.next = 0;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
std::size_t n = 0;
|
||||
for (; do_run_one(lock, this_thread, private_op_queue, ec); lock.lock())
|
||||
for (; do_run_one(lock, this_thread, ec); lock.lock())
|
||||
if (n != (std::numeric_limits<std::size_t>::max)())
|
||||
++n;
|
||||
return n;
|
||||
@@ -161,14 +168,13 @@ std::size_t task_io_service::run_one(boost::system::error_code& ec)
|
||||
thread_info this_thread;
|
||||
event wakeup_event;
|
||||
this_thread.wakeup_event = &wakeup_event;
|
||||
op_queue<operation> private_op_queue;
|
||||
this_thread.private_op_queue = 0;
|
||||
this_thread.private_outstanding_work = 0;
|
||||
this_thread.next = 0;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
return do_run_one(lock, this_thread, private_op_queue, ec);
|
||||
return do_run_one(lock, this_thread, ec);
|
||||
}
|
||||
|
||||
std::size_t task_io_service::poll(boost::system::error_code& ec)
|
||||
@@ -182,29 +188,23 @@ std::size_t task_io_service::poll(boost::system::error_code& ec)
|
||||
|
||||
thread_info this_thread;
|
||||
this_thread.wakeup_event = 0;
|
||||
op_queue<operation> private_op_queue;
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
this_thread.private_op_queue = one_thread_ == 1 ? &private_op_queue : 0;
|
||||
#else // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
this_thread.private_op_queue = 0;
|
||||
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
this_thread.private_outstanding_work = 0;
|
||||
this_thread.next = 0;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
// We want to support nested calls to poll() and poll_one(), so any handlers
|
||||
// that are already on a thread-private queue need to be put on to the main
|
||||
// queue now.
|
||||
if (one_thread_)
|
||||
if (thread_info* outer_thread_info = ctx.next_by_key())
|
||||
if (outer_thread_info->private_op_queue)
|
||||
op_queue_.push(*outer_thread_info->private_op_queue);
|
||||
op_queue_.push(outer_thread_info->private_op_queue);
|
||||
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
|
||||
std::size_t n = 0;
|
||||
for (; do_poll_one(lock, private_op_queue, ec); lock.lock())
|
||||
for (; do_poll_one(lock, this_thread, ec); lock.lock())
|
||||
if (n != (std::numeric_limits<std::size_t>::max)())
|
||||
++n;
|
||||
return n;
|
||||
@@ -221,24 +221,22 @@ std::size_t task_io_service::poll_one(boost::system::error_code& ec)
|
||||
|
||||
thread_info this_thread;
|
||||
this_thread.wakeup_event = 0;
|
||||
op_queue<operation> private_op_queue;
|
||||
this_thread.private_op_queue = 0;
|
||||
this_thread.private_outstanding_work = 0;
|
||||
this_thread.next = 0;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
// We want to support nested calls to poll() and poll_one(), so any handlers
|
||||
// that are already on a thread-private queue need to be put on to the main
|
||||
// queue now.
|
||||
if (one_thread_)
|
||||
if (thread_info* outer_thread_info = ctx.next_by_key())
|
||||
if (outer_thread_info->private_op_queue)
|
||||
op_queue_.push(*outer_thread_info->private_op_queue);
|
||||
op_queue_.push(outer_thread_info->private_op_queue);
|
||||
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
|
||||
return do_poll_one(lock, private_op_queue, ec);
|
||||
return do_poll_one(lock, this_thread, ec);
|
||||
}
|
||||
|
||||
void task_io_service::stop()
|
||||
@@ -261,22 +259,33 @@ void task_io_service::reset()
|
||||
|
||||
void task_io_service::post_immediate_completion(task_io_service::operation* op)
|
||||
{
|
||||
work_started();
|
||||
post_deferred_completion(op);
|
||||
}
|
||||
|
||||
void task_io_service::post_deferred_completion(task_io_service::operation* op)
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
if (one_thread_)
|
||||
{
|
||||
if (thread_info* this_thread = thread_call_stack::contains(this))
|
||||
{
|
||||
if (this_thread->private_op_queue)
|
||||
{
|
||||
this_thread->private_op_queue->push(op);
|
||||
return;
|
||||
}
|
||||
++this_thread->private_outstanding_work;
|
||||
this_thread->private_op_queue.push(op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
|
||||
work_started();
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue_.push(op);
|
||||
wake_one_thread_and_unlock(lock);
|
||||
}
|
||||
|
||||
void task_io_service::post_deferred_completion(task_io_service::operation* op)
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
if (one_thread_)
|
||||
{
|
||||
if (thread_info* this_thread = thread_call_stack::contains(this))
|
||||
{
|
||||
this_thread->private_op_queue.push(op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
@@ -291,16 +300,13 @@ void task_io_service::post_deferred_completions(
|
||||
{
|
||||
if (!ops.empty())
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
if (one_thread_)
|
||||
{
|
||||
if (thread_info* this_thread = thread_call_stack::contains(this))
|
||||
{
|
||||
if (this_thread->private_op_queue)
|
||||
{
|
||||
this_thread->private_op_queue->push(ops);
|
||||
return;
|
||||
}
|
||||
this_thread->private_op_queue.push(ops);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
@@ -311,6 +317,44 @@ void task_io_service::post_deferred_completions(
|
||||
}
|
||||
}
|
||||
|
||||
void task_io_service::post_private_immediate_completion(
|
||||
task_io_service::operation* op)
|
||||
{
|
||||
work_started();
|
||||
post_private_deferred_completion(op);
|
||||
}
|
||||
|
||||
void task_io_service::post_private_deferred_completion(
|
||||
task_io_service::operation* op)
|
||||
{
|
||||
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
if (thread_info* this_thread = thread_call_stack::contains(this))
|
||||
{
|
||||
this_thread->private_op_queue.push(op);
|
||||
return;
|
||||
}
|
||||
#endif // defined(BOOST_HAS_THREADS) && !defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue_.push(op);
|
||||
wake_one_thread_and_unlock(lock);
|
||||
}
|
||||
|
||||
void task_io_service::post_non_private_immediate_completion(
|
||||
task_io_service::operation* op)
|
||||
{
|
||||
work_started();
|
||||
post_non_private_deferred_completion(op);
|
||||
}
|
||||
|
||||
void task_io_service::post_non_private_deferred_completion(
|
||||
task_io_service::operation* op)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue_.push(op);
|
||||
wake_one_thread_and_unlock(lock);
|
||||
}
|
||||
|
||||
void task_io_service::abandon_operations(
|
||||
op_queue<task_io_service::operation>& ops)
|
||||
{
|
||||
@@ -320,7 +364,7 @@ void task_io_service::abandon_operations(
|
||||
|
||||
std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
|
||||
task_io_service::thread_info& this_thread,
|
||||
op_queue<operation>& private_op_queue, const boost::system::error_code& ec)
|
||||
const boost::system::error_code& ec)
|
||||
{
|
||||
while (!stopped_)
|
||||
{
|
||||
@@ -343,14 +387,13 @@ std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
|
||||
else
|
||||
lock.unlock();
|
||||
|
||||
op_queue<operation> completed_ops;
|
||||
task_cleanup on_exit = { this, &lock, &completed_ops };
|
||||
task_cleanup on_exit = { this, &lock, &this_thread };
|
||||
(void)on_exit;
|
||||
|
||||
// Run the task. May throw an exception. Only block if the operation
|
||||
// queue is empty and we're not polling, otherwise we want to return
|
||||
// as soon as possible.
|
||||
task_->run(!more_handlers, completed_ops);
|
||||
task_->run(!more_handlers, this_thread.private_op_queue);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -362,7 +405,7 @@ std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
|
||||
lock.unlock();
|
||||
|
||||
// Ensure the count of outstanding work is decremented on block exit.
|
||||
work_cleanup on_exit = { this, &lock, &private_op_queue };
|
||||
work_cleanup on_exit = { this, &lock, &this_thread };
|
||||
(void)on_exit;
|
||||
|
||||
// Complete the operation. May throw an exception. Deletes the object.
|
||||
@@ -385,7 +428,8 @@ std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
|
||||
}
|
||||
|
||||
std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
|
||||
op_queue<operation>& private_op_queue, const boost::system::error_code& ec)
|
||||
task_io_service::thread_info& this_thread,
|
||||
const boost::system::error_code& ec)
|
||||
{
|
||||
if (stopped_)
|
||||
return 0;
|
||||
@@ -397,14 +441,13 @@ std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
|
||||
lock.unlock();
|
||||
|
||||
{
|
||||
op_queue<operation> completed_ops;
|
||||
task_cleanup c = { this, &lock, &completed_ops };
|
||||
task_cleanup c = { this, &lock, &this_thread };
|
||||
(void)c;
|
||||
|
||||
// Run the task. May throw an exception. Only block if the operation
|
||||
// queue is empty and we're not polling, otherwise we want to return
|
||||
// as soon as possible.
|
||||
task_->run(false, completed_ops);
|
||||
task_->run(false, this_thread.private_op_queue);
|
||||
}
|
||||
|
||||
o = op_queue_.front();
|
||||
@@ -426,7 +469,7 @@ std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
|
||||
lock.unlock();
|
||||
|
||||
// Ensure the count of outstanding work is decremented on block exit.
|
||||
work_cleanup on_exit = { this, &lock, &private_op_queue };
|
||||
work_cleanup on_exit = { this, &lock, &this_thread };
|
||||
(void)on_exit;
|
||||
|
||||
// Complete the operation. May throw an exception. Deletes the object.
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
//
|
||||
// detail/impl/timer_queue.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 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_IMPL_TIMER_QUEUE_IPP
|
||||
#define BOOST_ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if !defined(BOOST_ASIO_HEADER_ONLY)
|
||||
|
||||
#include <boost/asio/detail/timer_queue.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
timer_queue<time_traits<boost::posix_time::ptime> >::timer_queue()
|
||||
{
|
||||
}
|
||||
|
||||
timer_queue<time_traits<boost::posix_time::ptime> >::~timer_queue()
|
||||
{
|
||||
}
|
||||
|
||||
bool timer_queue<time_traits<boost::posix_time::ptime> >::enqueue_timer(
|
||||
const time_type& time, per_timer_data& timer, timer_op* op)
|
||||
{
|
||||
return impl_.enqueue_timer(time, timer, op);
|
||||
}
|
||||
|
||||
bool timer_queue<time_traits<boost::posix_time::ptime> >::empty() const
|
||||
{
|
||||
return impl_.empty();
|
||||
}
|
||||
|
||||
long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_msec(
|
||||
long max_duration) const
|
||||
{
|
||||
return impl_.wait_duration_msec(max_duration);
|
||||
}
|
||||
|
||||
long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_usec(
|
||||
long max_duration) const
|
||||
{
|
||||
return impl_.wait_duration_usec(max_duration);
|
||||
}
|
||||
|
||||
void timer_queue<time_traits<boost::posix_time::ptime> >::get_ready_timers(
|
||||
op_queue<operation>& ops)
|
||||
{
|
||||
impl_.get_ready_timers(ops);
|
||||
}
|
||||
|
||||
void timer_queue<time_traits<boost::posix_time::ptime> >::get_all_timers(
|
||||
op_queue<operation>& ops)
|
||||
{
|
||||
impl_.get_all_timers(ops);
|
||||
}
|
||||
|
||||
std::size_t timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer(
|
||||
per_timer_data& timer, op_queue<operation>& ops, std::size_t max_cancelled)
|
||||
{
|
||||
return impl_.cancel_timer(timer, ops, max_cancelled);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // !defined(BOOST_ASIO_HEADER_ONLY)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
|
||||
@@ -33,7 +33,7 @@ namespace detail {
|
||||
template <typename Handler>
|
||||
void win_iocp_io_service::dispatch(Handler handler)
|
||||
{
|
||||
if (call_stack<win_iocp_io_service>::contains(this))
|
||||
if (thread_call_stack::contains(this))
|
||||
{
|
||||
fenced_block b(fenced_block::full);
|
||||
boost_asio_handler_invoke_helpers::invoke(handler, handler);
|
||||
|
||||
@@ -68,6 +68,7 @@ win_iocp_io_service::win_iocp_io_service(
|
||||
iocp_(),
|
||||
outstanding_work_(0),
|
||||
stopped_(0),
|
||||
stop_event_posted_(0),
|
||||
shutdown_(0),
|
||||
dispatch_required_(0)
|
||||
{
|
||||
@@ -148,12 +149,13 @@ size_t win_iocp_io_service::run(boost::system::error_code& ec)
|
||||
{
|
||||
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
|
||||
{
|
||||
InterlockedExchange(&stopped_, 1);
|
||||
stop();
|
||||
ec = boost::system::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<win_iocp_io_service>::context ctx(this);
|
||||
win_iocp_thread_info this_thread;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
size_t n = 0;
|
||||
while (do_one(true, ec))
|
||||
@@ -166,12 +168,13 @@ size_t win_iocp_io_service::run_one(boost::system::error_code& ec)
|
||||
{
|
||||
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
|
||||
{
|
||||
InterlockedExchange(&stopped_, 1);
|
||||
stop();
|
||||
ec = boost::system::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<win_iocp_io_service>::context ctx(this);
|
||||
win_iocp_thread_info this_thread;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
return do_one(true, ec);
|
||||
}
|
||||
@@ -180,12 +183,13 @@ size_t win_iocp_io_service::poll(boost::system::error_code& ec)
|
||||
{
|
||||
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
|
||||
{
|
||||
InterlockedExchange(&stopped_, 1);
|
||||
stop();
|
||||
ec = boost::system::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<win_iocp_io_service>::context ctx(this);
|
||||
win_iocp_thread_info this_thread;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
size_t n = 0;
|
||||
while (do_one(false, ec))
|
||||
@@ -198,12 +202,13 @@ size_t win_iocp_io_service::poll_one(boost::system::error_code& ec)
|
||||
{
|
||||
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
|
||||
{
|
||||
InterlockedExchange(&stopped_, 1);
|
||||
stop();
|
||||
ec = boost::system::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<win_iocp_io_service>::context ctx(this);
|
||||
win_iocp_thread_info this_thread;
|
||||
thread_call_stack::context ctx(this, this_thread);
|
||||
|
||||
return do_one(false, ec);
|
||||
}
|
||||
@@ -212,12 +217,15 @@ void win_iocp_io_service::stop()
|
||||
{
|
||||
if (::InterlockedExchange(&stopped_, 1) == 0)
|
||||
{
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
|
||||
if (::InterlockedExchange(&stop_event_posted_, 1) == 0)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
boost::system::error_code ec(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
boost::asio::detail::throw_error(ec, "pqcs");
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
boost::system::error_code ec(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
boost::asio::detail::throw_error(ec, "pqcs");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -421,17 +429,23 @@ size_t win_iocp_io_service::do_one(bool block, boost::system::error_code& ec)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Indicate that there is no longer an in-flight stop event.
|
||||
::InterlockedExchange(&stop_event_posted_, 0);
|
||||
|
||||
// The stopped_ flag is always checked to ensure that any leftover
|
||||
// interrupts from a previous run invocation are ignored.
|
||||
// stop events 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))
|
||||
if (::InterlockedExchange(&stop_event_posted_, 1) == 0)
|
||||
{
|
||||
last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
return 0;
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
|
||||
{
|
||||
last_error = ::GetLastError();
|
||||
ec = boost::system::error_code(last_error,
|
||||
boost::asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ec = boost::system::error_code();
|
||||
|
||||
@@ -43,11 +43,11 @@ int win_static_mutex::do_init()
|
||||
using namespace std; // For sprintf.
|
||||
wchar_t mutex_name[128];
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
|
||||
swprintf_s(mutex_name, 128,
|
||||
swprintf_s(
|
||||
#else // BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
|
||||
swprintf(mutex_name,
|
||||
_snwprintf(
|
||||
#endif // BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
|
||||
L"asio-58CCDC44-6264-4842-90C2-F3C545CB8AA7-%u-%p",
|
||||
mutex_name, 128, L"asio-58CCDC44-6264-4842-90C2-F3C545CB8AA7-%u-%p",
|
||||
static_cast<unsigned int>(::GetCurrentProcessId()), this);
|
||||
|
||||
HANDLE mutex = ::CreateMutexW(0, TRUE, mutex_name);
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// detail/keyword_tss_ptr.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2012 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_KEYWORD_TSS_PTR_HPP
|
||||
#define BOOST_ASIO_DETAIL_KEYWORD_TSS_PTR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
|
||||
|
||||
#include <boost/asio/detail/noncopyable.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename T>
|
||||
class keyword_tss_ptr
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
keyword_tss_ptr()
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
~keyword_tss_ptr()
|
||||
{
|
||||
}
|
||||
|
||||
// Get the value.
|
||||
operator T*() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
// Set the value.
|
||||
void operator=(T* value)
|
||||
{
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
static __thread T* value_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
__thread T* keyword_tss_ptr<T>::value_;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_KEYWORD_TSS_PTR_HPP
|
||||
@@ -129,8 +129,8 @@ BOOST_ASIO_DECL void init_buf(buf& b, void* data, size_t size);
|
||||
|
||||
BOOST_ASIO_DECL void init_buf(buf& b, const void* data, size_t size);
|
||||
|
||||
BOOST_ASIO_DECL int recv(socket_type s, buf* bufs, size_t count, int flags,
|
||||
boost::system::error_code& ec);
|
||||
BOOST_ASIO_DECL signed_size_type recv(socket_type s, buf* bufs,
|
||||
size_t count, int flags, boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs,
|
||||
size_t count, int flags, bool all_empty, boost::system::error_code& ec);
|
||||
@@ -149,9 +149,9 @@ BOOST_ASIO_DECL bool non_blocking_recv(socket_type s,
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
BOOST_ASIO_DECL 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);
|
||||
BOOST_ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,
|
||||
size_t count, int flags, socket_addr_type* addr,
|
||||
std::size_t* addrlen, boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
|
||||
buf* bufs, size_t count, int flags, socket_addr_type* addr,
|
||||
@@ -172,8 +172,9 @@ BOOST_ASIO_DECL bool non_blocking_recvfrom(socket_type s,
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
BOOST_ASIO_DECL int recvmsg(socket_type s, buf* bufs, size_t count,
|
||||
int in_flags, int& out_flags, boost::system::error_code& ec);
|
||||
BOOST_ASIO_DECL signed_size_type recvmsg(socket_type s, buf* bufs,
|
||||
size_t count, int in_flags, int& out_flags,
|
||||
boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL size_t sync_recvmsg(socket_type s, state_type state,
|
||||
buf* bufs, size_t count, int in_flags, int& out_flags,
|
||||
@@ -193,7 +194,7 @@ BOOST_ASIO_DECL bool non_blocking_recvmsg(socket_type s,
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
BOOST_ASIO_DECL int send(socket_type s, const buf* bufs,
|
||||
BOOST_ASIO_DECL signed_size_type send(socket_type s, const buf* bufs,
|
||||
size_t count, int flags, boost::system::error_code& ec);
|
||||
|
||||
BOOST_ASIO_DECL size_t sync_send(socket_type s, state_type state,
|
||||
@@ -214,9 +215,9 @@ BOOST_ASIO_DECL bool non_blocking_send(socket_type s,
|
||||
|
||||
#endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
|
||||
BOOST_ASIO_DECL 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);
|
||||
BOOST_ASIO_DECL signed_size_type 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);
|
||||
|
||||
BOOST_ASIO_DECL size_t sync_sendto(socket_type s, state_type state,
|
||||
const buf* bufs, size_t count, int flags, const socket_addr_type* addr,
|
||||
|
||||
@@ -107,6 +107,7 @@ typedef addrinfo addrinfo_type;
|
||||
typedef unsigned long ioctl_arg_type;
|
||||
typedef u_long u_long_type;
|
||||
typedef u_short u_short_type;
|
||||
typedef int signed_size_type;
|
||||
const int shutdown_receive = SD_RECEIVE;
|
||||
const int shutdown_send = SD_SEND;
|
||||
const int shutdown_both = SD_BOTH;
|
||||
@@ -156,6 +157,11 @@ typedef addrinfo addrinfo_type;
|
||||
typedef int ioctl_arg_type;
|
||||
typedef uint32_t u_long_type;
|
||||
typedef uint16_t u_short_type;
|
||||
#if defined(BOOST_ASIO_HAS_SSIZE_T)
|
||||
typedef ssize_t signed_size_type;
|
||||
#else // defined(BOOST_ASIO_HAS_SSIZE_T)
|
||||
typedef int signed_size_type;
|
||||
#endif // defined(BOOST_ASIO_HAS_SSIZE_T)
|
||||
const int shutdown_receive = SHUT_RD;
|
||||
const int shutdown_send = SHUT_WR;
|
||||
const int shutdown_both = SHUT_RDWR;
|
||||
|
||||
@@ -84,9 +84,6 @@ public:
|
||||
// Construct a new strand implementation.
|
||||
BOOST_ASIO_DECL void construct(implementation_type& impl);
|
||||
|
||||
// Destroy a strand implementation.
|
||||
void destroy(implementation_type& impl);
|
||||
|
||||
// Request the io_service to invoke the given handler.
|
||||
template <typename Handler>
|
||||
void dispatch(implementation_type& impl, Handler handler);
|
||||
|
||||
@@ -112,23 +112,41 @@ public:
|
||||
// that work_started() was previously called for each operation.
|
||||
BOOST_ASIO_DECL void post_deferred_completions(op_queue<operation>& ops);
|
||||
|
||||
// Request invocation of the given operation, preferring the thread-private
|
||||
// queue if available, and return immediately. Assumes that work_started()
|
||||
// has not yet been called for the operation.
|
||||
BOOST_ASIO_DECL void post_private_immediate_completion(operation* op);
|
||||
|
||||
// Request invocation of the given operation, preferring the thread-private
|
||||
// queue if available, and return immediately. Assumes that work_started()
|
||||
// was previously called for the operation.
|
||||
BOOST_ASIO_DECL void post_private_deferred_completion(operation* op);
|
||||
|
||||
// Process unfinished operations as part of a shutdown_service operation.
|
||||
// Assumes that work_started() was previously called for the operations.
|
||||
BOOST_ASIO_DECL void abandon_operations(op_queue<operation>& ops);
|
||||
|
||||
private:
|
||||
// Structure containing information about an idle thread.
|
||||
struct thread_info;
|
||||
typedef task_io_service_thread_info thread_info;
|
||||
|
||||
// Run at most one operation. Blocks only if this_idle_thread is non-null.
|
||||
// Request invocation of the given operation, avoiding the thread-private
|
||||
// queue, and return immediately. Assumes that work_started() has not yet
|
||||
// been called for the operation.
|
||||
BOOST_ASIO_DECL void post_non_private_immediate_completion(operation* op);
|
||||
|
||||
// Request invocation of the given operation, avoiding the thread-private
|
||||
// queue, and return immediately. Assumes that work_started() was previously
|
||||
// called for the operation.
|
||||
BOOST_ASIO_DECL void post_non_private_deferred_completion(operation* op);
|
||||
|
||||
// Run at most one operation. May block.
|
||||
BOOST_ASIO_DECL std::size_t do_run_one(mutex::scoped_lock& lock,
|
||||
thread_info& this_thread, op_queue<operation>& private_op_queue,
|
||||
const boost::system::error_code& ec);
|
||||
thread_info& this_thread, const boost::system::error_code& ec);
|
||||
|
||||
// Poll for at most one operation.
|
||||
BOOST_ASIO_DECL std::size_t do_poll_one(mutex::scoped_lock& lock,
|
||||
op_queue<operation>& private_op_queue,
|
||||
const boost::system::error_code& ec);
|
||||
thread_info& this_thread, const boost::system::error_code& ec);
|
||||
|
||||
// Stop the task and all idle threads.
|
||||
BOOST_ASIO_DECL void stop_all_threads(mutex::scoped_lock& lock);
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class task_io_service;
|
||||
class task_io_service_operation;
|
||||
struct task_io_service_thread_info;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// detail/task_io_service_thread_info.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2012 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_THREAD_INFO_HPP
|
||||
#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_THREAD_INFO_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/event.hpp>
|
||||
#include <boost/asio/detail/op_queue.hpp>
|
||||
#include <boost/asio/detail/task_io_service_fwd.hpp>
|
||||
#include <boost/asio/detail/thread_info_base.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
struct task_io_service_thread_info : public thread_info_base
|
||||
{
|
||||
event* wakeup_event;
|
||||
op_queue<task_io_service_operation> private_op_queue;
|
||||
long private_outstanding_work;
|
||||
task_io_service_thread_info* next;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_THREAD_INFO_HPP
|
||||
@@ -0,0 +1,93 @@
|
||||
//
|
||||
// detail/thread_info_base.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2012 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_INFO_BASE_HPP
|
||||
#define BOOST_ASIO_DETAIL_THREAD_INFO_BASE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <boost/asio/detail/noncopyable.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class thread_info_base
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
thread_info_base()
|
||||
: reusable_memory_(0)
|
||||
{
|
||||
}
|
||||
|
||||
~thread_info_base()
|
||||
{
|
||||
if (reusable_memory_)
|
||||
::operator delete(reusable_memory_);
|
||||
}
|
||||
|
||||
static void* allocate(thread_info_base* this_thread, std::size_t size)
|
||||
{
|
||||
if (this_thread && this_thread->reusable_memory_)
|
||||
{
|
||||
void* const pointer = this_thread->reusable_memory_;
|
||||
this_thread->reusable_memory_ = 0;
|
||||
|
||||
unsigned char* const mem = static_cast<unsigned char*>(pointer);
|
||||
if (static_cast<std::size_t>(mem[0]) >= size)
|
||||
{
|
||||
mem[size] = mem[0];
|
||||
return pointer;
|
||||
}
|
||||
|
||||
::operator delete(pointer);
|
||||
}
|
||||
|
||||
void* const pointer = ::operator new(size + 1);
|
||||
unsigned char* const mem = static_cast<unsigned char*>(pointer);
|
||||
mem[size] = (size <= UCHAR_MAX) ? static_cast<unsigned char>(size) : 0;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
static void deallocate(thread_info_base* this_thread,
|
||||
void* pointer, std::size_t size)
|
||||
{
|
||||
if (size <= UCHAR_MAX)
|
||||
{
|
||||
if (this_thread && this_thread->reusable_memory_ == 0)
|
||||
{
|
||||
unsigned char* const mem = static_cast<unsigned char*>(pointer);
|
||||
mem[0] = mem[size];
|
||||
this_thread->reusable_memory_ = pointer;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
::operator delete(pointer);
|
||||
}
|
||||
|
||||
private:
|
||||
void* reusable_memory_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_THREAD_INFO_BASE_HPP
|
||||
@@ -19,6 +19,8 @@
|
||||
|
||||
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
# include <boost/asio/detail/null_tss_ptr.hpp>
|
||||
#elif defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
|
||||
# include <boost/asio/detail/keyword_tss_ptr.hpp>
|
||||
#elif defined(BOOST_WINDOWS)
|
||||
# include <boost/asio/detail/win_tss_ptr.hpp>
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
@@ -37,6 +39,8 @@ template <typename T>
|
||||
class tss_ptr
|
||||
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
: public null_tss_ptr<T>
|
||||
#elif defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
|
||||
: public keyword_tss_ptr<T>
|
||||
#elif defined(BOOST_WINDOWS)
|
||||
: public win_tss_ptr<T>
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
@@ -48,6 +52,8 @@ public:
|
||||
{
|
||||
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_ASIO_DISABLE_THREADS)
|
||||
null_tss_ptr<T>::operator=(value);
|
||||
#elif defined(BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION)
|
||||
keyword_tss_ptr<T>::operator=(value);
|
||||
#elif defined(BOOST_WINDOWS)
|
||||
win_tss_ptr<T>::operator=(value);
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <boost/asio/detail/wait_op.hpp>
|
||||
#include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
|
||||
#include <boost/asio/detail/win_iocp_operation.hpp>
|
||||
#include <boost/asio/detail/win_iocp_thread_info.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
@@ -107,7 +108,7 @@ public:
|
||||
// Return whether a handler can be dispatched immediately.
|
||||
bool can_dispatch()
|
||||
{
|
||||
return call_stack<win_iocp_io_service>::contains(this) != 0;
|
||||
return thread_call_stack::contains(this) != 0;
|
||||
}
|
||||
|
||||
// Request invocation of the given handler.
|
||||
@@ -135,6 +136,22 @@ public:
|
||||
BOOST_ASIO_DECL void post_deferred_completions(
|
||||
op_queue<win_iocp_operation>& ops);
|
||||
|
||||
// Request invocation of the given operation using the thread-private queue
|
||||
// and return immediately. Assumes that work_started() has not yet been
|
||||
// called for the operation.
|
||||
void post_private_immediate_completion(win_iocp_operation* op)
|
||||
{
|
||||
post_immediate_completion(op);
|
||||
}
|
||||
|
||||
// Request invocation of the given operation using the thread-private queue
|
||||
// and return immediately. Assumes that work_started() was previously called
|
||||
// for the operation.
|
||||
void post_private_deferred_completion(win_iocp_operation* op)
|
||||
{
|
||||
post_deferred_completion(op);
|
||||
}
|
||||
|
||||
// Process unfinished operations as part of a shutdown_service operation.
|
||||
// Assumes that work_started() was previously called for the operations.
|
||||
BOOST_ASIO_DECL void abandon_operations(op_queue<operation>& ops);
|
||||
@@ -221,6 +238,11 @@ private:
|
||||
// Flag to indicate whether the event loop has been stopped.
|
||||
mutable long stopped_;
|
||||
|
||||
// Flag to indicate whether there is an in-flight stop event. Every event
|
||||
// posted using PostQueuedCompletionStatus consumes non-paged pool, so to
|
||||
// avoid exhausting this resouce we limit the number of outstanding events.
|
||||
long stop_event_posted_;
|
||||
|
||||
// Flag to indicate whether the service has been shut down.
|
||||
long shutdown_;
|
||||
|
||||
@@ -269,6 +291,10 @@ private:
|
||||
|
||||
// The operations that are ready to dispatch.
|
||||
op_queue<win_iocp_operation> completed_ops_;
|
||||
|
||||
// Per-thread call stack to track the state of each thread in the io_service.
|
||||
typedef call_stack<win_iocp_io_service,
|
||||
win_iocp_thread_info> thread_call_stack;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
@@ -446,7 +446,7 @@ protected:
|
||||
bool peer_is_open, socket_holder& new_socket, int family, int type,
|
||||
int protocol, void* output_buffer, DWORD address_length, operation* op);
|
||||
|
||||
// Start an asynchronous read or write operation using the the reactor.
|
||||
// Start an asynchronous read or write operation using the reactor.
|
||||
BOOST_ASIO_DECL void start_reactor_op(base_implementation_type& impl,
|
||||
int op_type, reactor_op* op);
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// detail/win_iocp_thread_info.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2012 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_THREAD_INFO_HPP
|
||||
#define BOOST_ASIO_DETAIL_WIN_IOCP_THREAD_INFO_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/thread_info_base.hpp>
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
struct win_iocp_thread_info : public thread_info_base
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_DETAIL_WIN_IOCP_THREAD_INFO_HPP
|
||||
@@ -32,10 +32,8 @@ namespace asio {
|
||||
* 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
|
||||
* The default implementation of these allocation hooks uses <tt>::operator
|
||||
* new</tt> and <tt>::operator delete</tt>.
|
||||
*
|
||||
* @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
|
||||
@@ -57,32 +55,29 @@ namespace asio {
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
inline void* asio_handler_allocate(std::size_t size, ...)
|
||||
{
|
||||
return ::operator new(size);
|
||||
}
|
||||
BOOST_ASIO_DECL void* asio_handler_allocate(
|
||||
std::size_t 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
|
||||
* The default implementation of these allocation hooks uses <tt>::operator
|
||||
* new</tt> and <tt>::operator delete</tt>.
|
||||
*
|
||||
* @sa asio_handler_allocate.
|
||||
*/
|
||||
inline void asio_handler_deallocate(void* pointer, std::size_t size, ...)
|
||||
{
|
||||
(void)(size);
|
||||
::operator delete(pointer);
|
||||
}
|
||||
BOOST_ASIO_DECL void asio_handler_deallocate(
|
||||
void* pointer, std::size_t size, ...);
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#if defined(BOOST_ASIO_HEADER_ONLY)
|
||||
# include <boost/asio/impl/handler_alloc_hook.ipp>
|
||||
#endif // defined(BOOST_ASIO_HEADER_ONLY)
|
||||
|
||||
#endif // BOOST_ASIO_HANDLER_ALLOC_HOOK_HPP
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace detail {
|
||||
class netdb_category : public boost::system::error_category
|
||||
{
|
||||
public:
|
||||
const char* name() const
|
||||
const char* name() const BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT
|
||||
{
|
||||
return "asio.netdb";
|
||||
}
|
||||
@@ -63,7 +63,7 @@ namespace detail {
|
||||
class addrinfo_category : public boost::system::error_category
|
||||
{
|
||||
public:
|
||||
const char* name() const
|
||||
const char* name() const BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT
|
||||
{
|
||||
return "asio.addrinfo";
|
||||
}
|
||||
@@ -93,7 +93,7 @@ namespace detail {
|
||||
class misc_category : public boost::system::error_category
|
||||
{
|
||||
public:
|
||||
const char* name() const
|
||||
const char* name() const BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT
|
||||
{
|
||||
return "asio.misc";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// impl/handler_alloc_hook.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2012 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_IMPL_HANDLER_ALLOC_HOOK_IPP
|
||||
#define BOOST_ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include <boost/asio/detail/config.hpp>
|
||||
#include <boost/asio/detail/call_stack.hpp>
|
||||
#include <boost/asio/handler_alloc_hook.hpp>
|
||||
|
||||
#if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
# if defined(BOOST_ASIO_HAS_IOCP)
|
||||
# include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
|
||||
# include <boost/asio/detail/win_iocp_thread_info.hpp>
|
||||
# else // defined(BOOST_ASIO_HAS_IOCP)
|
||||
# include <boost/asio/detail/task_io_service_thread_info.hpp>
|
||||
# endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
#endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
|
||||
#include <boost/asio/detail/push_options.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace asio {
|
||||
|
||||
void* asio_handler_allocate(std::size_t size, ...)
|
||||
{
|
||||
#if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
# if defined(BOOST_ASIO_HAS_IOCP)
|
||||
typedef detail::win_iocp_io_service io_service_impl;
|
||||
typedef detail::win_iocp_thread_info thread_info;
|
||||
# else // defined(BOOST_ASIO_HAS_IOCP)
|
||||
typedef detail::task_io_service io_service_impl;
|
||||
typedef detail::task_io_service_thread_info thread_info;
|
||||
# endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
typedef detail::call_stack<io_service_impl, thread_info> call_stack;
|
||||
return thread_info::allocate(call_stack::top(), size);
|
||||
#else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
return ::operator new(size);
|
||||
#endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
}
|
||||
|
||||
void asio_handler_deallocate(void* pointer, std::size_t size, ...)
|
||||
{
|
||||
#if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
# if defined(BOOST_ASIO_HAS_IOCP)
|
||||
typedef detail::win_iocp_io_service io_service_impl;
|
||||
typedef detail::win_iocp_thread_info thread_info;
|
||||
# else // defined(BOOST_ASIO_HAS_IOCP)
|
||||
typedef detail::task_io_service io_service_impl;
|
||||
typedef detail::task_io_service_thread_info thread_info;
|
||||
# endif // defined(BOOST_ASIO_HAS_IOCP)
|
||||
typedef detail::call_stack<io_service_impl, thread_info> call_stack;
|
||||
thread_info::deallocate(call_stack::top(), pointer, size);
|
||||
#else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
(void)size;
|
||||
::operator delete(pointer);
|
||||
#endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
|
||||
}
|
||||
|
||||
} // namespace asio
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/asio/detail/pop_options.hpp>
|
||||
|
||||
#endif // BOOST_ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user