Project import
diff --git a/boost/Android.mk b/boost/Android.mk new file mode 100644 index 0000000..3edb66c --- /dev/null +++ b/boost/Android.mk
@@ -0,0 +1 @@ +include $(call all-subdir-makefiles,$(LOCAL_PATH))
diff --git a/boost/INSTALL b/boost/INSTALL new file mode 100644 index 0000000..0f669e6 --- /dev/null +++ b/boost/INSTALL
@@ -0,0 +1,8 @@ +See ./index.html for information about this release. The "Getting Started" +section is a useful starting place. + +--------------------------- +Copyright Beman Dawes, 2008 + +Distributed under the Boost Software License, Version 1.0. +See ./LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt \ No newline at end of file
diff --git a/boost/Jamroot b/boost/Jamroot new file mode 100644 index 0000000..dec428c --- /dev/null +++ b/boost/Jamroot
@@ -0,0 +1,293 @@ +# Copyright Vladimir Prus 2002-2006. +# Copyright Dave Abrahams 2005-2006. +# Copyright Rene Rivera 2005-2007. +# Copyright Douglas Gregor 2005. +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# Usage: +# +# b2 [options] [properties] [install|stage] +# +# Builds and installs Boost. +# +# Targets and Related Options: +# +# install Install headers and compiled library files to the +# ======= configured locations (below). +# +# --prefix=<PREFIX> Install architecture independent files here. +# Default; C:\Boost on Win32 +# Default; /usr/local on Unix. Linux, etc. +# +# --exec-prefix=<EPREFIX> Install architecture dependent files here. +# Default; <PREFIX> +# +# --libdir=<DIR> Install library files here. +# Default; <EPREFIX>/lib +# +# --includedir=<HDRDIR> Install header files here. +# Default; <PREFIX>/include +# +# stage Build and install only compiled library files to the +# ===== stage directory. +# +# --stagedir=<STAGEDIR> Install library files here +# Default; ./stage +# +# Other Options: +# +# --build-type=<type> Build the specified pre-defined set of variations of +# the libraries. Note, that which variants get built +# depends on what each library supports. +# +# -- minimal -- (default) Builds a minimal set of +# variants. On Windows, these are static +# multithreaded libraries in debug and release +# modes, using shared runtime. On Linux, these are +# static and shared multithreaded libraries in +# release mode. +# +# -- complete -- Build all possible variations. +# +# --build-dir=DIR Build in this location instead of building within +# the distribution tree. Recommended! +# +# --show-libraries Display the list of Boost libraries that require +# build and installation steps, and then exit. +# +# --layout=<layout> Determine whether to choose library names and header +# locations such that multiple versions of Boost or +# multiple compilers can be used on the same system. +# +# -- versioned -- Names of boost binaries include +# the Boost version number, name and version of +# the compiler and encoded build properties. Boost +# headers are installed in a subdirectory of +# <HDRDIR> whose name contains the Boost version +# number. +# +# -- tagged -- Names of boost binaries include the +# encoded build properties such as variant and +# threading, but do not including compiler name +# and version, or Boost version. This option is +# useful if you build several variants of Boost, +# using the same compiler. +# +# -- system -- Binaries names do not include the +# Boost version number or the name and version +# number of the compiler. Boost headers are +# installed directly into <HDRDIR>. This option is +# intended for system integrators building +# distribution packages. +# +# The default value is 'versioned' on Windows, and +# 'system' on Unix. +# +# --buildid=ID Add the specified ID to the name of built libraries. +# The default is to not add anything. +# +# --python-buildid=ID Add the specified ID to the name of built libraries +# that depend on Python. The default is to not add +# anything. This ID is added in addition to --buildid. +# +# --help This message. +# +# --with-<library> Build and install the specified <library>. If this +# option is used, only libraries specified using this +# option will be built. +# +# --without-<library> Do not build, stage, or install the specified +# <library>. By default, all libraries are built. +# +# Properties: +# +# toolset=toolset Indicate the toolset to build with. +# +# variant=debug|release Select the build variant +# +# link=static|shared Whether to build static or shared libraries +# +# threading=single|multi Whether to build single or multithreaded binaries +# +# runtime-link=static|shared +# Whether to link to static or shared C and C++ +# runtime. +# + +# TODO: +# - handle boost version +# - handle python options such as pydebug + +import boostcpp ; +import package ; + +import sequence ; +import xsltproc ; +import set ; +import path ; +import link ; + +path-constant BOOST_ROOT : . ; +constant BOOST_VERSION : 1.58.0 ; +constant BOOST_JAMROOT_MODULE : $(__name__) ; + +boostcpp.set-version $(BOOST_VERSION) ; + +use-project /boost/architecture : libs/config/checks/architecture ; + +local all-headers = + [ MATCH .*libs/(.*)/include/boost : [ glob libs/*/include/boost ] ] ; + +for dir in $(all-headers) +{ + link-directory $(dir)-headers : libs/$(dir)/include/boost : <location>. ; + explicit $(dir)-headers ; +} + +local numeric-headers = + [ MATCH .*libs/numeric/(.*)/include/boost : [ glob libs/*/*/include/boost ] ] ; + +for dir in $(numeric-headers) +{ + link-directory numeric-$(dir)-headers : libs/numeric/$(dir)/include/boost : <location>. ; + explicit numeric-$(dir)-headers ; +} + +if $(all-headers) +{ + constant BOOST_MODULARLAYOUT : $(all-headers) $(numeric-headers) ; +} + +project boost + : requirements <include>. + + [ boostcpp.architecture ] + [ boostcpp.address-model ] + + # Disable auto-linking for all targets here, primarily because it caused + # troubles with V2. + <define>BOOST_ALL_NO_LIB=1 + # Used to encode variant in target name. See the 'tag' rule below. + <tag>@$(__name__).tag + <conditional>@handle-static-runtime + # The standard library Sun compilers use by default has no chance + # of working with Boost. Override it. + <toolset>sun:<stdlib>sun-stlport + # Comeau does not support shared lib + <toolset>como:<link>static + <toolset>como-linux:<define>_GNU_SOURCE=1 + # When building docs within Boost, we want the standard Boost style + <xsl:param>boost.defaults=Boost + : usage-requirements <include>. + : build-dir bin.v2 + ; + +# This rule is called by Boost.Build to determine the name of target. We use it +# to encode the build variant, compiler name and boost version in the target +# name. +# +rule tag ( name : type ? : property-set ) +{ + return [ boostcpp.tag $(name) : $(type) : $(property-set) ] ; +} + +rule handle-static-runtime ( properties * ) +{ + # Using static runtime with shared libraries is impossible on Linux, and + # dangerous on Windows. Therefore, we disallow it. This might be drastic, + # but it was disabled for a while without anybody complaining. + + # For CW, static runtime is needed so that std::locale works. + if <link>shared in $(properties) && <runtime-link>static in $(properties) && + ! ( <toolset>cw in $(properties) ) + { + ECHO "error: link=shared together with runtime-link=static is not allowed" ; + ECHO "error: such property combination is either impossible " ; + ECHO "error: or too dangerious to be of any use" ; + EXIT ; + } +} + +all-libraries = [ MATCH .*libs/(.*)/build/.* : [ glob libs/*/build/Jamfile.v2 ] + [ glob libs/*/build/Jamfile ] ] ; + +all-libraries = [ sequence.unique $(all-libraries) ] ; +# The function_types library has a Jamfile, but it's used for maintenance +# purposes, there's no library to build and install. +all-libraries = [ set.difference $(all-libraries) : function_types ] ; + +# Setup convenient aliases for all libraries. + +local rule explicit-alias ( id : targets + ) +{ + alias $(id) : $(targets) ; + explicit $(id) ; +} + +# First, the complicated libraries: where the target name in Jamfile is +# different from its directory name. +explicit-alias prg_exec_monitor : libs/test/build//boost_prg_exec_monitor ; +explicit-alias test_exec_monitor : libs/test/build//boost_test_exec_monitor ; +explicit-alias unit_test_framework : libs/test/build//boost_unit_test_framework ; +explicit-alias bgl-vis : libs/graps/build//bgl-vis ; +explicit-alias serialization : libs/serialization/build//boost_serialization ; +explicit-alias wserialization : libs/serialization/build//boost_wserialization ; +for local l in $(all-libraries) +{ + if ! $(l) in test graph serialization + { + explicit-alias $(l) : libs/$(l)/build//boost_$(l) ; + } +} + +alias headers : $(all-headers)-headers numeric-$(numeric-headers)-headers : : : <include>. ; +explicit headers ; + +# Make project ids of all libraries known. +for local l in $(all-libraries) +{ + use-project /boost/$(l) : libs/$(l)/build ; +} + +use-project /boost/tools/inspect : tools/inspect/build ; +use-project /boost/libs/wave/tool : libs/wave/tool/build ; + +# This rule should be called from libraries' Jamfiles and will create two +# targets, "install" and "stage", that will install or stage that library. The +# --prefix option is respected, but --with and --without options, naturally, are +# ignored. +# +# - libraries -- list of library targets to install. +# +rule boost-install ( libraries * ) +{ + package.install install + : <dependency>/boost//install-proper-headers $(install-requirements) + : # No binaries + : $(libraries) + : # No headers, it is handled by the dependency. + ; + + install stage : $(libraries) : <location>$(BOOST_STAGE_LOCATE) ; + + module [ CALLER_MODULE ] + { + explicit stage ; + explicit install ; + } +} + +headers = + # The .SUNWCCh files are present in tr1 include directory and have to be + # installed (see http://lists.boost.org/Archives/boost/2007/05/121430.php). + [ path.glob-tree $(BOOST_ROOT)/boost : *.hpp *.ipp *.h *.inc *.SUNWCCh : CVS .svn ] + [ path.glob-tree $(BOOST_ROOT)/boost/compatibility/cpp_c_headers : c* : CVS .svn ] + [ path.glob boost/tr1/tr1 : * : bcc32 sun CVS .svn ] + ; + +# Declare special top-level targets that build and install the desired variants +# of the libraries. +boostcpp.declare-targets $(all-libraries) : $(headers) ;
diff --git a/boost/LICENSE b/boost/LICENSE new file mode 100644 index 0000000..36b7cd9 --- /dev/null +++ b/boost/LICENSE
@@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE.
diff --git a/boost/LICENSE_1_0.txt b/boost/LICENSE_1_0.txt new file mode 100644 index 0000000..36b7cd9 --- /dev/null +++ b/boost/LICENSE_1_0.txt
@@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE.
diff --git a/boost/MODULE_LICENSE_BSD_LIKE b/boost/MODULE_LICENSE_BSD_LIKE new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/boost/MODULE_LICENSE_BSD_LIKE
diff --git a/boost/android/build/boost-common-decl.mk b/boost/android/build/boost-common-decl.mk new file mode 100644 index 0000000..f666c5b --- /dev/null +++ b/boost/android/build/boost-common-decl.mk
@@ -0,0 +1,2 @@ +EXTERNAL_BOOST_LOCAL_PATH := external/boost +EXTERNAL_BOOST_COMMON := $(EXTERNAL_BOOST_LOCAL_PATH)/android/build/boost-common.mk
diff --git a/boost/android/build/boost-common.mk b/boost/android/build/boost-common.mk new file mode 100644 index 0000000..19d73ae --- /dev/null +++ b/boost/android/build/boost-common.mk
@@ -0,0 +1,8 @@ +# Because of b/25560842 : +LOCAL_CLANG := false +LOCAL_C_INCLUDES += $(EXTERNAL_BOOST_LOCAL_PATH) +# per Jamroot: "Disable auto-linking for all targets here, primarily because it caused troubles with V2" +LOCAL_CFLAGS += -DBOOST_ALL_NO_LIB=1 +LOCAL_RTTI_FLAG := -frtti +LOCAL_CPPFLAGS += -fexceptions +LOCAL_SHARED_LIBRARIES += libc++
diff --git a/boost/android/test/boost-generic-test-runner.sh b/boost/android/test/boost-generic-test-runner.sh new file mode 100755 index 0000000..0632be0 --- /dev/null +++ b/boost/android/test/boost-generic-test-runner.sh
@@ -0,0 +1,177 @@ +#!/system/bin/sh +# +# Copyright 2015 Nest Labs, Inc. All rights reserved. + +if [ -z "$PACKAGE" ] ; then + PACKAGE="boost-generic-test-runner" +fi + +if [ -z "$TEST_ROOT" ] ; then + TEST_ROOT="$(dirname $0)" + grep -vE "^/" "$TEST_ROOT" &> /dev/null + if [ $? -eq 0 ] ; then + TEST_ROOT="$(pwd)/${TEST_ROOT}" + fi +fi +THIS_SCRIPT="$(basename $0)" + +### +### GLOBAL VARIABLES +### +### only export variables that mutate +### + +# Increment when a test passes +export GLOBAL_PASS=0 +# Increment when a test fails +export GLOBAL_FAIL=0 +# The directory where helper test programs are installed +TEST_BIN="${TEST_ROOT}/bin" +# The directory where helper test data is installed +TEST_DATA="${TEST_ROOT}/data" +# The temporary directory where raw program output is placed +TMPDIR=/storage +# The log file with all raw program output +LOGFILE=$(mktemp --tmpdir="${TMPDIR}" ${PACKAGE}-log.XXXXXXXX) +# A temporary file, usually used for staging raw program output for grep +TMPFILE=$(mktemp --tmpdir="${TMPDIR}" ${PACKAGE}-tmp.XXXXXXXX) + +# The scripts need their PATH set, too +export PATH="${TEST_BIN}:${PATH}" + +# run_test +# +# This is a /bin/sh port of add_gflags_test that is implemented by +# cmake/utils.cmake and cmake/execute_test.cmake +# +# Usage: run_test <test-name> <expected-return-code> <expected-text-output> <unexpected-text-output> <cmd> [args...] +# +# test-name: A symbolic name for the test for logging +# +# expected-return-code: the number passed back to the operating system. default: 0 +# if a blank string is given. +# +# expected-text-output: if a non-empty string, it is expected that the command will +# output this string. It must be seen in order to pass. +# +# unexpected-text-output: if a non-empty string, it is expected that the command +# will NOT output this string. If it is seen, the test will fail. +# +# cmd: executable to run (full path or in $PATH) +# +# args: all arguments that need to be passed on to the executable. +# +run_test() +{ + TEST_NAME="$1" + shift + EXPECTED_RC="$1" + shift + EXPECTED_OUTPUT="$1" + shift + UNEXPECTED_OUTPUT="$1" + shift + + if [ $# -eq 0 ] ; then + GLOBAL_RETURN_CODE=1 + echo "FATAL ERROR: invalid arguments passed to run_test for test='$TEST_NAME'" + return 1 + fi + + if [ -z "$EXPECTED_RC" ] ; then + EXPECTED_RC="0" + fi + + VERDICT="pass" + REASON="default" + + echo "RUNNING TEST '${TEST_NAME}' >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" > "$TMPFILE" + echo "CMDLINE: $@" >> "$TMPFILE" + "$@" &>> "$TMPFILE" + RC=$? + echo "RC=$RC" >> "$TMPFILE" + echo "END OF TEST '${TEST_NAME}' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> "$TMPFILE" + + EXPECTED_FOUND=1 + UNEXPECTED_FOUND=0 + + if [ -n "$EXPECTED_OUTPUT" ] ; then + grep -- "$EXPECTED_OUTPUT" "$TMPFILE" &> /dev/null + if [ $? -ne 0 ] ; then + EXPECTED_FOUND=0 + fi + fi + + if [ -n "$UNEXPECTED_OUTPUT" ] ; then + grep -- "$UNEXPECTED_OUTPUT" "$TMPFILE" &> /dev/null + if [ $? -eq 0 ] ; then + UNEXPECTED_FOUND=1 + fi + fi + + if [ "$RC" != "$EXPECTED_RC" ] ; then + VERDICT="fail" + REASON="unexpected return code (got ${RC}, expected ${EXPECTED_RC})" + elif [ "$EXPECTED_FOUND" = "0" ] ; then + VERDICT="fail" + REASON="missing expected output, expected '${EXPECTED_OUTPUT}', see '$LOGFILE'" + elif [ "$UNEXPECTED_FOUND" = "1" ] ; then + VERDICT="fail" + REASON="Unexpected output detected: '${UNEXPECTED_OUTPUT}', see '$LOGFILE'" + fi + + cat "$TMPFILE" >> "$LOGFILE" + + if [ "$VERDICT" = "pass" ] ; then + echo "${TEST_NAME}: pass" + GLOBAL_PASS=$(($GLOBAL_PASS + 1)) + return 0 + else + echo "${TEST_NAME}: fail ($REASON)" + GLOBAL_FAIL=$(($GLOBAL_FAIL + 1)) + return 1 + fi +} + +# Tests must be executed from here: +cd "$TEST_ROOT" + +### +### TEST CASES +### + +# Test this script +run_test "the_truth" 0 "" "" true +run_test "the_lie" 1 "" "" false +run_test "the_word" "" "really unlikely" "" echo "really unlikely" + +for T in "${TEST_BIN}"/* ; do + NAME=$(basename "${T}") + if [ "x${NAME}" == "x${THIS_SCRIPT}" ] ; then + continue + fi + if [ ! -f "${T}" ] ; then + continue + fi + if [ ! -x "${T}" ] ; then + echo "${NAME}: fail (file in bin/ folder without execute permission)" + continue + fi + run_test "$NAME" 0 "" "" "$T" +done + +### +### RESULTS +### + +if [ $GLOBAL_FAIL -ne 0 ] ; then + RETURN_CODE=1 +else + RETURN_CODE=0 +fi +TOTAL_TESTS=$(($GLOBAL_PASS + $GLOBAL_FAIL)) + +echo "${GLOBAL_PASS}/${TOTAL_TESTS} passed. See '$LOGFILE'" +rm "$TMPFILE" + +exit $RETURN_CODE
diff --git a/boost/boost-build.jam b/boost/boost-build.jam new file mode 100644 index 0000000..0d54b5b --- /dev/null +++ b/boost/boost-build.jam
@@ -0,0 +1,17 @@ +# Copyright (C) 2002-2003 David Abrahams. +# Copyright (C) 2002-2003 Vladimir Prus. +# Copyright (C) 2003,2007 Rene Rivera. +# Use, modification and distribution are subject to the +# Boost Software License, Version 1.0. (See accompanying file +# LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +# This is the initial file loaded by Boost Jam when run from any Boost library +# folder. It allows us to choose which Boost Build installation to use for +# building Boost libraries. Unless explicitly selected using a command-line +# option, the version included with the Boost library distribution is used (as +# opposed to any other Boost Build version installed on the user's sytem). + +BOOST_ROOT = $(.boost-build-file:D) ; +BOOST_BUILD = [ MATCH --boost-build=(.*) : $(ARGV) ] ; +BOOST_BUILD ?= tools/build/src ; +boost-build $(BOOST_BUILD) ;
diff --git a/boost/boost.css b/boost/boost.css new file mode 100644 index 0000000..986c405 --- /dev/null +++ b/boost/boost.css
@@ -0,0 +1,66 @@ +/*============================================================================= + Copyright 2002 William E. Kempf + Distributed under the Boost Software License, Version 1.0. (See accompany- + ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +H1 +{ + FONT-SIZE: 200%; + COLOR: #00008B; +} +H2 +{ + FONT-SIZE: 150%; +} +H3 +{ + FONT-SIZE: 125%; +} +H4 +{ + FONT-SIZE: 108%; +} +BODY +{ + FONT-SIZE: 100%; + BACKGROUND-COLOR: #ffffff; + COLOR: #000000; +} +PRE +{ + MARGIN-LEFT: 2em; + FONT-FAMILY: Courier, + monospace; +} +CODE +{ + FONT-FAMILY: Courier, + monospace; +} +CODE.as_pre +{ + white-space: pre; +} +.index +{ + TEXT-ALIGN: left; +} +.page-index +{ + TEXT-ALIGN: left; +} +.definition +{ + TEXT-ALIGN: left; +} +.footnote +{ + FONT-SIZE: 66%; + VERTICAL-ALIGN: super; + TEXT-DECORATION: none; +} +.function-semantics +{ + CLEAR: left; +} \ No newline at end of file
diff --git a/boost/boost.png b/boost/boost.png new file mode 100644 index 0000000..b4d51fc --- /dev/null +++ b/boost/boost.png Binary files differ
diff --git a/boost/boost/accumulators/accumulators.hpp b/boost/boost/accumulators/accumulators.hpp new file mode 100644 index 0000000..55ee2f9 --- /dev/null +++ b/boost/boost/accumulators/accumulators.hpp
@@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file accumulators.hpp +/// Includes all of the Accumulators Framework +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_ACCUMULATORS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_ACCUMULATORS_HPP_EAN_28_10_2005 + +#include <boost/accumulators/framework/accumulator_set.hpp> +#include <boost/accumulators/framework/accumulator_concept.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/external.hpp> +#include <boost/accumulators/framework/features.hpp> +#include <boost/accumulators/framework/parameters/accumulator.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/framework/parameters/weight.hpp> +#include <boost/accumulators/framework/parameters/weights.hpp> +#include <boost/accumulators/framework/accumulators/external_accumulator.hpp> +#include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp> +#include <boost/accumulators/framework/accumulators/reference_accumulator.hpp> +#include <boost/accumulators/framework/accumulators/value_accumulator.hpp> + +#endif
diff --git a/boost/boost/accumulators/accumulators_fwd.hpp b/boost/boost/accumulators/accumulators_fwd.hpp new file mode 100644 index 0000000..4c0370e --- /dev/null +++ b/boost/boost/accumulators/accumulators_fwd.hpp
@@ -0,0 +1,230 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulators_fwd.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_ACCUMULATORS_FWD_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_ACCUMULATORS_FWD_HPP_EAN_28_10_2005 + +#include <boost/config.hpp> +#include <boost/mpl/apply_fwd.hpp> // for mpl::na +#include <boost/mpl/limits/vector.hpp> +#include <boost/preprocessor/cat.hpp> +#include <boost/preprocessor/arithmetic/inc.hpp> +#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp> +#include <boost/preprocessor/repetition/enum_trailing_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/accumulators/numeric/functional_fwd.hpp> + +#ifndef BOOST_ACCUMULATORS_MAX_FEATURES + /// The maximum number of accumulators that may be put in an accumulator_set. + /// Defaults to BOOST_MPL_LIMIT_VECTOR_SIZE (which defaults to 20). +# define BOOST_ACCUMULATORS_MAX_FEATURES BOOST_MPL_LIMIT_VECTOR_SIZE +#endif + +#if BOOST_ACCUMULATORS_MAX_FEATURES > BOOST_MPL_LIMIT_VECTOR_SIZE +# error BOOST_ACCUMULATORS_MAX_FEATURES cannot be larger than BOOST_MPL_LIMIT_VECTOR_SIZE +#endif + +#ifndef BOOST_ACCUMULATORS_MAX_ARGS + /// The maximum number of arguments that may be specified to an accumulator_set's + /// accumulation function. Defaults to 15. +# define BOOST_ACCUMULATORS_MAX_ARGS 15 +#endif + +#if BOOST_WORKAROUND(__GNUC__, == 3) \ + || BOOST_WORKAROUND(__EDG_VERSION__, BOOST_TESTED_AT(306)) +# define BOOST_ACCUMULATORS_BROKEN_CONST_OVERLOADS +#endif + +#ifdef BOOST_ACCUMULATORS_BROKEN_CONST_OVERLOADS +# include <boost/utility/enable_if.hpp> +# include <boost/type_traits/is_const.hpp> +# define BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(T)\ + , typename boost::disable_if<boost::is_const<T> >::type * = 0 +#else +# define BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(T) +#endif + +#define BOOST_ACCUMULATORS_GCC_VERSION \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// Named parameters tags +// +namespace tag +{ + struct sample; + struct weight; + struct accumulator; + struct weights; +} + +/////////////////////////////////////////////////////////////////////////////// +// User-level features +// +namespace tag +{ + template<typename ValueType, typename Tag> + struct value; + + template<typename Tag> + struct value_tag; + + template<typename Referent, typename Tag> + struct reference; + + template<typename Tag> + struct reference_tag; + + template<typename Type, typename Tag = void, typename AccumulatorSet = void> + struct external; + + template<typename Feature> + struct droppable; +} + +template<typename Accumulator> +struct droppable_accumulator_base; + +template<typename Accumulator> +struct droppable_accumulator; + +template<typename Accumulator> +struct with_cached_result; + +template<typename Sample, typename Features, typename Weight = void> +struct accumulator_set; + +template<typename Feature> +struct extractor; + +template<typename Feature> +struct feature_of; + +template<typename Feature> +struct as_feature; + +template<typename Feature> +struct as_weighted_feature; + +template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature, mpl::na)> +struct depends_on; + +template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature, mpl::na)> +struct features; + +template<typename Feature, typename AccumulatorSet> +typename mpl::apply<AccumulatorSet, Feature>::type const & +find_accumulator(AccumulatorSet const &acc); + +template<typename Feature, typename AccumulatorSet> +typename mpl::apply<AccumulatorSet, Feature>::type::result_type +extract_result(AccumulatorSet const &acc); + +template<typename Feature, typename AccumulatorSet, typename A1> +typename mpl::apply<AccumulatorSet, Feature>::type::result_type +extract_result(AccumulatorSet const &acc, A1 const &a1); + +// ... other overloads generated by Boost.Preprocessor: + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FWD(z, n, _) \ + template< \ + typename Feature \ + , typename AccumulatorSet \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ + > \ + typename mpl::apply<AccumulatorSet, Feature>::type::result_type \ + extract_result( \ + AccumulatorSet const &acc \ + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ + ); + +/// INTERNAL ONLY +/// +BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_EXTRACT_RESULT_FWD + , _ +) + +#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED +template<typename Feature, typename AccumulatorSet, typename A1, typename A2 ...> +typename mpl::apply<AccumulatorSet, Feature>::type::result_type +extract_result(AccumulatorSet const &acc, A1 const &a1, A2 const &a2 ...); +#endif + +namespace impl +{ + using namespace numeric::operators; + + template<typename Accumulator, typename Tag> + struct external_impl; +} + +namespace detail +{ + template<typename Accumulator> + struct feature_tag; + + template<typename Feature, typename Sample, typename Weight> + struct to_accumulator; + + struct accumulator_set_base; + + template<typename T> + struct is_accumulator_set; + + inline void ignore_variable(void const *) {} + +#define BOOST_ACCUMULATORS_IGNORE_GLOBAL(X) \ + namespace detail \ + { \ + struct BOOST_PP_CAT(ignore_, X) \ + { \ + void ignore() \ + { \ + boost::accumulators::detail::ignore_variable(&X); \ + } \ + }; \ + } \ + /**/ +} + +}} // namespace boost::accumulators + +// For defining boost::parameter keywords that can be inherited from to +// get a nested, class-scoped keyword with the requested alias +#define BOOST_PARAMETER_NESTED_KEYWORD(tag_namespace, name, alias) \ + namespace tag_namespace \ + { \ + template<int Dummy = 0> \ + struct name ## _ \ + { \ + static char const* keyword_name() \ + { \ + return #name; \ + } \ + static ::boost::parameter::keyword<name ## _<Dummy> > &alias; \ + }; \ + template<int Dummy> \ + ::boost::parameter::keyword<name ## _<Dummy> > &name ## _<Dummy>::alias = \ + ::boost::parameter::keyword<name ## _<Dummy> >::get(); \ + typedef name ## _ <> name; \ + } \ + namespace \ + { \ + ::boost::parameter::keyword<tag_namespace::name> &name = \ + ::boost::parameter::keyword<tag_namespace::name>::get(); \ + } + +#endif
diff --git a/boost/boost/accumulators/framework/accumulator_base.hpp b/boost/boost/accumulators/framework/accumulator_base.hpp new file mode 100644 index 0000000..52c520d --- /dev/null +++ b/boost/boost/accumulators/framework/accumulator_base.hpp
@@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulator_base.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_BASE_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_BASE_HPP_EAN_28_10_2005 + +#include <boost/mpl/placeholders.hpp> +#include <boost/mpl/joint_view.hpp> +#include <boost/mpl/single_view.hpp> +#include <boost/mpl/fold.hpp> +#include <boost/mpl/contains.hpp> +#include <boost/mpl/empty_sequence.hpp> +#include <boost/accumulators/framework/accumulator_concept.hpp> + +namespace boost { namespace accumulators +{ + +namespace detail +{ + typedef void void_; +} + +/////////////////////////////////////////////////////////////////////////////// +// dont_care +// +struct dont_care +{ + template<typename Args> + dont_care(Args const &) + { + } +}; + +/////////////////////////////////////////////////////////////////////////////// +// accumulator_base +// +struct accumulator_base +{ + // hidden if defined in derived classes + detail::void_ operator ()(dont_care) + { + } + + typedef mpl::false_ is_droppable; + + detail::void_ add_ref(dont_care) + { + } + + detail::void_ drop(dont_care) + { + } + + detail::void_ on_drop(dont_care) + { + } +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/accumulator_concept.hpp b/boost/boost/accumulators/framework/accumulator_concept.hpp new file mode 100644 index 0000000..492357e --- /dev/null +++ b/boost/boost/accumulators/framework/accumulator_concept.hpp
@@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulator_concept.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_CONCEPT_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_CONCEPT_HPP_EAN_28_10_2005 + +#include <boost/concept_check.hpp> + +namespace boost { namespace accumulators +{ + +template<typename Stat> +struct accumulator_concept +{ + void constraints() + { + // TODO: define the stat concept + } + + Stat stat; +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/accumulator_set.hpp b/boost/boost/accumulators/framework/accumulator_set.hpp new file mode 100644 index 0000000..ed1ceb1 --- /dev/null +++ b/boost/boost/accumulators/framework/accumulator_set.hpp
@@ -0,0 +1,401 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulator_set.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATOR_SET_HPP_EAN_28_10_2005 + +#include <boost/version.hpp> +#include <boost/mpl/apply.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/mpl/protect.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/is_sequence.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/parameter/parameters.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/preprocessor/repetition/enum_binary_params.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/framework/accumulator_concept.hpp> +#include <boost/accumulators/framework/parameters/accumulator.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/framework/accumulators/external_accumulator.hpp> +#include <boost/accumulators/framework/accumulators/droppable_accumulator.hpp> +#include <boost/fusion/include/any.hpp> +#include <boost/fusion/include/find_if.hpp> +#include <boost/fusion/include/for_each.hpp> +#include <boost/fusion/include/filter_view.hpp> + +namespace boost { namespace accumulators +{ + +namespace detail +{ + /////////////////////////////////////////////////////////////////////////////// + // accumulator_visitor + // wrap a boost::parameter argument pack in a Fusion extractor object + template<typename Args> + struct accumulator_visitor + { + explicit accumulator_visitor(Args const &a) + : args(a) + { + } + + template<typename Accumulator> + void operator ()(Accumulator &accumulator) const + { + accumulator(this->args); + } + + private: + accumulator_visitor &operator =(accumulator_visitor const &); + Args const &args; + }; + + template<typename Args> + inline accumulator_visitor<Args> const make_accumulator_visitor(Args const &args) + { + return accumulator_visitor<Args>(args); + } + + typedef + parameter::parameters< + parameter::required<tag::accumulator> + , parameter::optional<tag::sample> + // ... and others which are not specified here... + > + accumulator_params; + + /////////////////////////////////////////////////////////////////////////////// + // accumulator_set_base + struct accumulator_set_base + { + }; + + /////////////////////////////////////////////////////////////////////////////// + // is_accumulator_set + template<typename T> + struct is_accumulator_set + : is_base_and_derived<accumulator_set_base, T> + { + }; + +} // namespace detail + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4355) // warning C4355: 'this' : used in base member initializer list +#endif + +/////////////////////////////////////////////////////////////////////////////// +/// \brief A set of accumulators. +/// +/// accumulator_set resolves the dependencies between features and ensures that +/// the accumulators in the set are updated in the proper order. +/// +/// acccumulator_set provides a general mechanism to visit the accumulators +/// in the set in order, with or without a filter. You can also fetch a reference +/// to an accumulator that corresponds to a feature. +/// +template<typename Sample, typename Features, typename Weight> +struct accumulator_set + : detail::accumulator_set_base +{ + typedef Sample sample_type; ///< The type of the samples that will be accumulated + typedef Features features_type; ///< An MPL sequence of the features that should be accumulated. + typedef Weight weight_type; ///< The type of the weight parameter. Must be a scalar. Defaults to void. + + /// INTERNAL ONLY + /// + typedef + typename detail::make_accumulator_tuple< + Features + , Sample + , Weight + >::type + accumulators_mpl_vector; + + // generate a fusion::list of accumulators + /// INTERNAL ONLY + /// + typedef + typename detail::meta::make_acc_list< + accumulators_mpl_vector + >::type + accumulators_type; + + /// INTERNAL ONLY + /// + //BOOST_MPL_ASSERT((mpl::is_sequence<accumulators_type>)); + + /////////////////////////////////////////////////////////////////////////////// + /// default-construct all contained accumulators + accumulator_set() + : accumulators( + detail::make_acc_list( + accumulators_mpl_vector() + , detail::accumulator_params()(*this) + ) + ) + { + // Add-ref the Features that the user has specified + this->template visit_if<detail::contains_feature_of_<Features> >( + detail::make_add_ref_visitor(detail::accumulator_params()(*this)) + ); + } + + /// \overload + /// + /// \param a1 Optional named parameter to be passed to all the accumulators + template<typename A1> + explicit accumulator_set(A1 const &a1) + : accumulators( + detail::make_acc_list( + accumulators_mpl_vector() + , detail::accumulator_params()(*this, a1) + ) + ) + { + // Add-ref the Features that the user has specified + this->template visit_if<detail::contains_feature_of_<Features> >( + detail::make_add_ref_visitor(detail::accumulator_params()(*this)) + ); + } + + // ... other overloads generated by Boost.Preprocessor: + + /// INTERNAL ONLY + /// +#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR(z, n, _) \ + template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ + accumulator_set(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \ + : accumulators( \ + detail::make_acc_list( \ + accumulators_mpl_vector() \ + , detail::accumulator_params()( \ + *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ + ) \ + ) \ + ) \ + { \ + /* Add-ref the Features that the user has specified */ \ + this->template visit_if<detail::contains_feature_of_<Features> >( \ + detail::make_add_ref_visitor(detail::accumulator_params()(*this)) \ + ); \ + } + + /// INTERNAL ONLY + /// + BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_ACCUMULATOR_SET_CTOR + , _ + ) + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// \overload + /// + template<typename A1, typename A2, ...> + accumulator_set(A1 const &a1, A2 const &a2, ...); + #endif + + // ... other overloads generated by Boost.Preprocessor below ... + + /////////////////////////////////////////////////////////////////////////////// + /// Visitation + /// \param func UnaryFunction which is invoked with each accumulator in turn. + template<typename UnaryFunction> + void visit(UnaryFunction const &func) + { + fusion::for_each(this->accumulators, func); + } + + /////////////////////////////////////////////////////////////////////////////// + /// Conditional visitation + /// \param func UnaryFunction which is invoked with each accumulator in turn, + /// provided the accumulator satisfies the MPL predicate FilterPred. + template<typename FilterPred, typename UnaryFunction> + void visit_if(UnaryFunction const &func) + { + fusion::filter_view<accumulators_type, FilterPred> filtered_accs(this->accumulators); + fusion::for_each(filtered_accs, func); + } + + /////////////////////////////////////////////////////////////////////////////// + /// The return type of the operator() overloads is void. + typedef void result_type; + + /////////////////////////////////////////////////////////////////////////////// + /// Accumulation + /// \param a1 Optional named parameter to be passed to all the accumulators + void operator ()() + { + this->visit( + detail::make_accumulator_visitor( + detail::accumulator_params()(*this) + ) + ); + } + + template<typename A1> + void operator ()(A1 const &a1) + { + this->visit( + detail::make_accumulator_visitor( + detail::accumulator_params()(*this, a1) + ) + ); + } + + // ... other overloads generated by Boost.Preprocessor: + + /// INTERNAL ONLY + /// +#define BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP(z, n, _) \ + template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ + void operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) \ + { \ + this->visit( \ + detail::make_accumulator_visitor( \ + detail::accumulator_params()( \ + *this BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ + ) \ + ) \ + ); \ + } + + /// INTERNAL ONLY + /// + BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_ACCUMULATOR_SET_FUN_OP + , _ + ) + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// \overload + /// + template<typename A1, typename A2, ...> + void operator ()(A1 const &a1, A2 const &a2, ...); + #endif + + /////////////////////////////////////////////////////////////////////////////// + /// Extraction + template<typename Feature> + struct apply + : fusion::result_of::value_of< + typename fusion::result_of::find_if< + accumulators_type + , detail::matches_feature<Feature> + >::type + > + { + }; + + /////////////////////////////////////////////////////////////////////////////// + /// Extraction + template<typename Feature> + typename apply<Feature>::type &extract() + { + return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators); + } + + /// \overload + template<typename Feature> + typename apply<Feature>::type const &extract() const + { + return *fusion::find_if<detail::matches_feature<Feature> >(this->accumulators); + } + + /////////////////////////////////////////////////////////////////////////////// + /// Drop + template<typename Feature> + void drop() + { + // You can only drop the features that you have specified explicitly + typedef typename apply<Feature>::type the_accumulator; + BOOST_MPL_ASSERT((detail::contains_feature_of<Features, the_accumulator>)); + + typedef + typename feature_of<typename as_feature<Feature>::type>::type + the_feature; + + (*fusion::find_if<detail::matches_feature<Feature> >(this->accumulators)) + .drop(detail::accumulator_params()(*this)); + + // Also drop accumulators that this feature depends on + typedef typename the_feature::dependencies dependencies; + this->template visit_if<detail::contains_feature_of_<dependencies> >( + detail::make_drop_visitor(detail::accumulator_params()(*this)) + ); + } + +private: + + accumulators_type accumulators; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +/////////////////////////////////////////////////////////////////////////////// +// find_accumulator +// find an accumulator in an accumulator_set corresponding to a feature +template<typename Feature, typename AccumulatorSet> +typename mpl::apply<AccumulatorSet, Feature>::type & +find_accumulator(AccumulatorSet &acc BOOST_ACCUMULATORS_PROTO_DISABLE_IF_IS_CONST(AccumulatorSet)) +{ + return acc.template extract<Feature>(); +} + +/// \overload +template<typename Feature, typename AccumulatorSet> +typename mpl::apply<AccumulatorSet, Feature>::type const & +find_accumulator(AccumulatorSet const &acc) +{ + return acc.template extract<Feature>(); +} + +/////////////////////////////////////////////////////////////////////////////// +// extract_result +// extract a result from an accumulator set +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN(z, n, _) \ + template< \ + typename Feature \ + , typename AccumulatorSet \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ + > \ + typename mpl::apply<AccumulatorSet, Feature>::type::result_type \ + extract_result( \ + AccumulatorSet const &acc \ + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ + ) \ + { \ + return find_accumulator<Feature>(acc).result( \ + detail::accumulator_params()( \ + acc \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a) \ + ) \ + ); \ + } + +BOOST_PP_REPEAT( + BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_EXTRACT_RESULT_FUN + , _ +) + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/accumulators/droppable_accumulator.hpp b/boost/boost/accumulators/framework/accumulators/droppable_accumulator.hpp new file mode 100644 index 0000000..0e882b5 --- /dev/null +++ b/boost/boost/accumulators/framework/accumulators/droppable_accumulator.hpp
@@ -0,0 +1,328 @@ +/////////////////////////////////////////////////////////////////////////////// +// droppable_accumulator.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_DROPPABLE_ACCUMULATOR_HPP_EAN_13_12_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_DROPPABLE_ACCUMULATOR_HPP_EAN_13_12_2005 + +#include <new> +#include <boost/assert.hpp> +#include <boost/mpl/apply.hpp> +#include <boost/aligned_storage.hpp> +#include <boost/accumulators/framework/depends_on.hpp> // for feature_of +#include <boost/accumulators/framework/parameters/accumulator.hpp> // for accumulator + +namespace boost { namespace accumulators +{ + + template<typename Accumulator> + struct droppable_accumulator; + + namespace detail + { + /////////////////////////////////////////////////////////////////////////////// + // add_ref_visitor + // a fusion function object for add_ref'ing accumulators + template<typename Args> + struct add_ref_visitor + { + explicit add_ref_visitor(Args const &args) + : args_(args) + { + } + + template<typename Accumulator> + void operator ()(Accumulator &acc) const + { + typedef typename Accumulator::feature_tag::dependencies dependencies; + + acc.add_ref(this->args_); + + // Also add_ref accumulators that this feature depends on + this->args_[accumulator].template + visit_if<detail::contains_feature_of_<dependencies> >( + *this + ); + } + + private: + add_ref_visitor &operator =(add_ref_visitor const &); + Args const &args_; + }; + + template<typename Args> + add_ref_visitor<Args> make_add_ref_visitor(Args const &args) + { + return add_ref_visitor<Args>(args); + } + + /////////////////////////////////////////////////////////////////////////////// + // drop_visitor + // a fusion function object for dropping accumulators + template<typename Args> + struct drop_visitor + { + explicit drop_visitor(Args const &args) + : args_(args) + { + } + + template<typename Accumulator> + void operator ()(Accumulator &acc) const + { + if(typename Accumulator::is_droppable()) + { + typedef typename Accumulator::feature_tag::dependencies dependencies; + + acc.drop(this->args_); + // Also drop accumulators that this feature depends on + this->args_[accumulator].template + visit_if<detail::contains_feature_of_<dependencies> >( + *this + ); + } + } + + private: + drop_visitor &operator =(drop_visitor const &); + Args const &args_; + }; + + template<typename Args> + drop_visitor<Args> make_drop_visitor(Args const &args) + { + return drop_visitor<Args>(args); + } + } + + ////////////////////////////////////////////////////////////////////////// + // droppable_accumulator_base + template<typename Accumulator> + struct droppable_accumulator_base + : Accumulator + { + typedef droppable_accumulator_base base; + typedef mpl::true_ is_droppable; + typedef typename Accumulator::result_type result_type; + + template<typename Args> + droppable_accumulator_base(Args const &args) + : Accumulator(args) + , ref_count_(0) + { + } + + 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) + { + if(!this->is_dropped()) + { + this->Accumulator::operator ()(args); + } + } + + template<typename Args> + void add_ref(Args const &) + { + ++this->ref_count_; + } + + template<typename Args> + void drop(Args const &args) + { + BOOST_ASSERT(0 < this->ref_count_); + if(1 == this->ref_count_) + { + static_cast<droppable_accumulator<Accumulator> *>(this)->on_drop(args); + } + --this->ref_count_; + } + + bool is_dropped() const + { + return 0 == this->ref_count_; + } + + private: + int ref_count_; + }; + + ////////////////////////////////////////////////////////////////////////// + // droppable_accumulator + // this can be specialized for any type that needs special handling + template<typename Accumulator> + struct droppable_accumulator + : droppable_accumulator_base<Accumulator> + { + template<typename Args> + droppable_accumulator(Args const &args) + : droppable_accumulator::base(args) + { + } + + droppable_accumulator(droppable_accumulator const &that) + : droppable_accumulator::base(*static_cast<typename droppable_accumulator::base const *>(&that)) + { + } + }; + + ////////////////////////////////////////////////////////////////////////// + // with_cached_result + template<typename Accumulator> + struct with_cached_result + : Accumulator + { + typedef typename Accumulator::result_type result_type; + + template<typename Args> + with_cached_result(Args const &args) + : Accumulator(args) + , cache() + { + } + + with_cached_result(with_cached_result const &that) + : Accumulator(*static_cast<Accumulator const *>(&that)) + , cache() + { + if(that.has_result()) + { + this->set(that.get()); + } + } + + ~with_cached_result() + { + // Since this is a base class of droppable_accumulator_base, + // this destructor is called before any of droppable_accumulator_base's + // members get cleaned up, including is_dropped, so the following + // call to has_result() is valid. + if(this->has_result()) + { + this->get().~result_type(); + } + } + + template<typename Args> + void on_drop(Args const &args) + { + // cache the result at the point this calculation was dropped + BOOST_ASSERT(!this->has_result()); + this->set(this->Accumulator::result(args)); + } + + template<typename Args> + result_type result(Args const &args) const + { + return this->has_result() ? this->get() : this->Accumulator::result(args); + } + + private: + with_cached_result &operator =(with_cached_result const &); + + void set(result_type const &r) + { + ::new(this->cache.address()) result_type(r); + } + + result_type const &get() const + { + return *static_cast<result_type const *>(this->cache.address()); + } + + bool has_result() const + { + typedef with_cached_result<Accumulator> this_type; + typedef droppable_accumulator_base<this_type> derived_type; + return static_cast<derived_type const *>(this)->is_dropped(); + } + + aligned_storage<sizeof(result_type)> cache; + }; + + namespace tag + { + template<typename Feature> + struct as_droppable + { + typedef droppable<Feature> type; + }; + + template<typename Feature> + struct as_droppable<droppable<Feature> > + { + typedef droppable<Feature> type; + }; + + ////////////////////////////////////////////////////////////////////////// + // droppable + template<typename Feature> + struct droppable + : as_feature<Feature>::type + { + typedef typename as_feature<Feature>::type feature_type; + typedef typename feature_type::dependencies tmp_dependencies_; + + typedef + typename mpl::transform< + typename feature_type::dependencies + , as_droppable<mpl::_1> + >::type + dependencies; + + struct impl + { + template<typename Sample, typename Weight> + struct apply + { + typedef + droppable_accumulator< + typename mpl::apply2<typename feature_type::impl, Sample, Weight>::type + > + type; + }; + }; + }; + } + + // make droppable<tag::feature(modifier)> work + template<typename Feature> + struct as_feature<tag::droppable<Feature> > + { + typedef tag::droppable<typename as_feature<Feature>::type> type; + }; + + // make droppable<tag::mean> work with non-void weights (should become + // droppable<tag::weighted_mean> + template<typename Feature> + struct as_weighted_feature<tag::droppable<Feature> > + { + typedef tag::droppable<typename as_weighted_feature<Feature>::type> type; + }; + + // for the purposes of feature-based dependency resolution, + // droppable<Foo> provides the same feature as Foo + template<typename Feature> + struct feature_of<tag::droppable<Feature> > + : feature_of<Feature> + { + }; + + // Note: Usually, the extractor is pulled into the accumulators namespace with + // a using directive, not the tag. But the droppable<> feature doesn't have an + // extractor, so we can put the droppable tag in the accumulators namespace + // without fear of a name conflict. + using tag::droppable; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/accumulators/external_accumulator.hpp b/boost/boost/accumulators/framework/accumulators/external_accumulator.hpp new file mode 100644 index 0000000..71dce42 --- /dev/null +++ b/boost/boost/accumulators/framework/accumulators/external_accumulator.hpp
@@ -0,0 +1,108 @@ +/////////////////////////////////////////////////////////////////////////////// +// external_accumulator.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_EXTERNAL_ACCUMULATOR_HPP_EAN_01_12_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_EXTERNAL_ACCUMULATOR_HPP_EAN_01_12_2005 + +#include <boost/mpl/placeholders.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/depends_on.hpp> // for feature_tag +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/accumulators/reference_accumulator.hpp> + +namespace boost { namespace accumulators { namespace impl +{ + + ////////////////////////////////////////////////////////////////////////// + // external_impl + /// INTERNAL ONLY + /// + template<typename Accumulator, typename Tag> + struct external_impl + : accumulator_base + { + typedef typename Accumulator::result_type result_type; + typedef typename detail::feature_tag<Accumulator>::type feature_tag; + + external_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + return this->extract_(args, args[parameter::keyword<Tag>::get() | 0]); + } + + private: + + template<typename Args> + static result_type extract_(Args const &args, int) + { + // No named parameter passed to the extractor. Maybe the external + // feature is held by reference<>. + extractor<feature_tag> extract; + return extract(accumulators::reference_tag<Tag>(args)); + } + + template<typename Args, typename AccumulatorSet> + static result_type extract_(Args const &, AccumulatorSet const &acc) + { + // OK, a named parameter for this external feature was passed to the + // extractor, so use that. + extractor<feature_tag> extract; + return extract(acc); + } + }; + +} // namespace impl + +namespace tag +{ + ////////////////////////////////////////////////////////////////////////// + // external + template<typename Feature, typename Tag, typename AccumulatorSet> + struct external + : depends_on<reference<AccumulatorSet, Tag> > + { + typedef + accumulators::impl::external_impl< + detail::to_accumulator<Feature, mpl::_1, mpl::_2> + , Tag + > + impl; + }; + + template<typename Feature, typename Tag> + struct external<Feature, Tag, void> + : depends_on<> + { + typedef + accumulators::impl::external_impl< + detail::to_accumulator<Feature, mpl::_1, mpl::_2> + , Tag + > + impl; + }; +} + +// for the purposes of feature-based dependency resolution, +// external_accumulator<Feature, Tag> provides the same feature as Feature +template<typename Feature, typename Tag, typename AccumulatorSet> +struct feature_of<tag::external<Feature, Tag, AccumulatorSet> > + : feature_of<Feature> +{ +}; + +// Note: Usually, the extractor is pulled into the accumulators namespace with +// a using directive, not the tag. But the external<> feature doesn't have an +// extractor, so we can put the external tag in the accumulators namespace +// without fear of a name conflict. +using tag::external; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/accumulators/reference_accumulator.hpp b/boost/boost/accumulators/framework/accumulators/reference_accumulator.hpp new file mode 100644 index 0000000..bf4252c --- /dev/null +++ b/boost/boost/accumulators/framework/accumulators/reference_accumulator.hpp
@@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////// +// reference_accumulator.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_REFERENCE_ACCUMULATOR_HPP_EAN_03_23_2006 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_REFERENCE_ACCUMULATOR_HPP_EAN_03_23_2006 + +#include <boost/ref.hpp> +#include <boost/mpl/always.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/accumulators/framework/depends_on.hpp> // for feature_tag +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + ////////////////////////////////////////////////////////////////////////// + // reference_accumulator_impl + // + template<typename Referent, typename Tag> + struct reference_accumulator_impl + : accumulator_base + { + typedef Referent &result_type; + + template<typename Args> + reference_accumulator_impl(Args const &args) + : ref(args[parameter::keyword<Tag>::get()]) + { + } + + result_type result(dont_care) const + { + return this->ref; + } + + private: + reference_wrapper<Referent> ref; + }; +} // namespace impl + +namespace tag +{ + ////////////////////////////////////////////////////////////////////////// + // reference_tag + template<typename Tag> + struct reference_tag + { + }; + + ////////////////////////////////////////////////////////////////////////// + // reference + template<typename Referent, typename Tag> + struct reference + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef mpl::always<accumulators::impl::reference_accumulator_impl<Referent, Tag> > impl; + }; +} + +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, reference, (typename)(typename)) + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, reference_tag, (typename)) +} + +using extract::reference; +using extract::reference_tag; + +// Map all reference<V,T> features to reference_tag<T> so +// that references can be extracted using reference_tag<T> +// without specifying the referent type. +template<typename ValueType, typename Tag> +struct feature_of<tag::reference<ValueType, Tag> > + : feature_of<tag::reference_tag<Tag> > +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/accumulators/value_accumulator.hpp b/boost/boost/accumulators/framework/accumulators/value_accumulator.hpp new file mode 100644 index 0000000..02bf7f3 --- /dev/null +++ b/boost/boost/accumulators/framework/accumulators/value_accumulator.hpp
@@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////// +// value_accumulator.hpp +// +// Copyright 2005 Eric Niebler, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_VALUE_ACCUMULATOR_HPP_EAN_03_23_2006 +#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_VALUE_ACCUMULATOR_HPP_EAN_03_23_2006 + +#include <boost/mpl/always.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/accumulators/framework/depends_on.hpp> // for feature_tag +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + ////////////////////////////////////////////////////////////////////////// + // value_accumulator_impl + template<typename ValueType, typename Tag> + struct value_accumulator_impl + : accumulator_base + { + typedef ValueType result_type; + + template<typename Args> + value_accumulator_impl(Args const &args) + : val(args[parameter::keyword<Tag>::get()]) + { + } + + result_type result(dont_care) const + { + return this->val; + } + + private: + ValueType val; + }; + +} // namespace impl + +namespace tag +{ + ////////////////////////////////////////////////////////////////////////// + // value_tag + template<typename Tag> + struct value_tag + { + }; + + ////////////////////////////////////////////////////////////////////////// + // value + template<typename ValueType, typename Tag> + struct value + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef mpl::always<accumulators::impl::value_accumulator_impl<ValueType, Tag> > impl; + }; +} + +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, value, (typename)(typename)) + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, value_tag, (typename)) +} + +using extract::value; +using extract::value_tag; + +// Map all value<V,T> features to value_tag<T> so +// that values can be extracted using value_tag<T> +// without specifying the value type. +template<typename ValueType, typename Tag> +struct feature_of<tag::value<ValueType, Tag> > + : feature_of<tag::value_tag<Tag> > +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/depends_on.hpp b/boost/boost/accumulators/framework/depends_on.hpp new file mode 100644 index 0000000..008f121 --- /dev/null +++ b/boost/boost/accumulators/framework/depends_on.hpp
@@ -0,0 +1,448 @@ +/////////////////////////////////////////////////////////////////////////////// +// depends_on.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_DEPENDS_ON_HPP_EAN_28_10_2005 + +#include <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> +#include <boost/mpl/insert.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/mpl/remove.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/inherit.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/equal_to.hpp> +#include <boost/mpl/contains.hpp> +#include <boost/mpl/transform.hpp> +#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> +#include <boost/preprocessor/repetition/repeat.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/facilities/intercept.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> +#include <boost/fusion/include/next.hpp> +#include <boost/fusion/include/equal_to.hpp> +#include <boost/fusion/include/value_of.hpp> +#include <boost/fusion/include/mpl.hpp> +#include <boost/fusion/include/end.hpp> +#include <boost/fusion/include/begin.hpp> +#include <boost/fusion/include/cons.hpp> + +namespace boost { namespace accumulators +{ + /////////////////////////////////////////////////////////////////////////// + // as_feature + template<typename Feature> + struct as_feature + { + typedef Feature type; + }; + + /////////////////////////////////////////////////////////////////////////// + // weighted_feature + template<typename Feature> + struct as_weighted_feature + { + typedef Feature type; + }; + + /////////////////////////////////////////////////////////////////////////// + // feature_of + template<typename Feature> + struct feature_of + { + typedef Feature type; + }; + + namespace detail + { + /////////////////////////////////////////////////////////////////////////// + // feature_tag + template<typename Accumulator> + struct feature_tag + { + typedef typename Accumulator::feature_tag type; + }; + + template<typename Feature> + struct undroppable + { + typedef Feature type; + }; + + template<typename Feature> + struct undroppable<tag::droppable<Feature> > + { + typedef Feature type; + }; + + // For the purpose of determining whether one feature depends on another, + // disregard whether the feature is droppable or not. + template<typename A, typename B> + struct is_dependent_on + : is_base_and_derived< + 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< + 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> + , mpl::_1 + , mpl::inherit<mpl::_1, mpl::_2> + > + >::type + { + }; + } + + /////////////////////////////////////////////////////////////////////////// + /// depends_on + template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)> + struct depends_on + : detail::depends_on_base< + typename mpl::transform< + mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)> + , as_feature<mpl::_1> + >::type + > + { + typedef mpl::false_ is_weight_accumulator; + typedef + typename mpl::transform< + mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)> + , as_feature<mpl::_1> + >::type + dependencies; + }; + + namespace detail + { + template<typename Feature> + struct matches_feature + { + template<typename Accumulator> + struct apply + : is_same< + typename feature_of<typename as_feature<Feature>::type>::type + , typename feature_of<typename as_feature<typename feature_tag<Accumulator>::type>::type>::type + > + {}; + }; + + template<typename Features, typename Accumulator> + struct contains_feature_of + { + typedef + mpl::transform_view<Features, feature_of<as_feature<mpl::_> > > + features_list; + + typedef + typename feature_of<typename feature_tag<Accumulator>::type>::type + the_feature; + + typedef + typename mpl::contains<features_list, the_feature>::type + type; + }; + + // This is to work around a bug in early versions of Fusion which caused + // a compile error if contains_feature_of<List, mpl::_> is used as a + // predicate to fusion::find_if + template<typename Features> + struct contains_feature_of_ + { + template<typename Accumulator> + struct apply + : contains_feature_of<Features, Accumulator> + {}; + }; + + template< + typename First + , typename Last + , bool is_empty = fusion::result_of::equal_to<First, Last>::value + > + struct build_acc_list; + + template<typename First, typename Last> + struct build_acc_list<First, Last, true> + { + typedef fusion::nil_ type; + + template<typename Args> + static fusion::nil_ + call(Args const &, First const&, Last const&) + { + return fusion::nil_(); + } + }; + + template<typename First, typename Last> + struct build_acc_list<First, Last, false> + { + typedef + build_acc_list<typename fusion::result_of::next<First>::type, Last> + next_build_acc_list; + + typedef fusion::cons< + typename fusion::result_of::value_of<First>::type + , typename next_build_acc_list::type> + type; + + template<typename Args> + static type + call(Args const &args, First const& f, Last const& l) + { + return type(args, next_build_acc_list::call(args, fusion::next(f), l)); + } + }; + + namespace meta + { + template<typename Sequence> + struct make_acc_list + : build_acc_list< + typename fusion::result_of::begin<Sequence>::type + , typename fusion::result_of::end<Sequence>::type + > + {}; + } + + template<typename Sequence, typename Args> + typename meta::make_acc_list<Sequence>::type + make_acc_list(Sequence const &seq, Args const &args) + { + return meta::make_acc_list<Sequence>::call(args, fusion::begin(seq), fusion::end(seq)); + } + + /////////////////////////////////////////////////////////////////////////// + // checked_as_weighted_feature + template<typename Feature> + struct checked_as_weighted_feature + { + typedef typename as_feature<Feature>::type feature_type; + typedef typename as_weighted_feature<feature_type>::type type; + // weighted and non-weighted flavors should provide the same feature. + BOOST_MPL_ASSERT(( + is_same< + typename feature_of<feature_type>::type + , typename feature_of<type>::type + > + )); + }; + + /////////////////////////////////////////////////////////////////////////// + // as_feature_list + template<typename Features, typename Weight> + struct as_feature_list + : mpl::transform_view<Features, checked_as_weighted_feature<mpl::_1> > + { + }; + + template<typename Features> + struct as_feature_list<Features, void> + : mpl::transform_view<Features, as_feature<mpl::_1> > + { + }; + + /////////////////////////////////////////////////////////////////////////// + // accumulator_wrapper + template<typename Accumulator, typename Feature> + struct accumulator_wrapper + : Accumulator + { + typedef Feature feature_tag; + + accumulator_wrapper(accumulator_wrapper const &that) + : Accumulator(*static_cast<Accumulator const *>(&that)) + { + } + + template<typename Args> + accumulator_wrapper(Args const &args) + : Accumulator(args) + { + } + }; + + /////////////////////////////////////////////////////////////////////////// + // to_accumulator + template<typename Feature, typename Sample, typename Weight> + struct to_accumulator + { + typedef + accumulator_wrapper< + typename mpl::apply2<typename Feature::impl, Sample, Weight>::type + , Feature + > + type; + }; + + template<typename Feature, typename Sample, typename Weight, typename Tag, typename AccumulatorSet> + struct to_accumulator<Feature, Sample, tag::external<Weight, Tag, AccumulatorSet> > + { + BOOST_MPL_ASSERT((is_same<Tag, void>)); + BOOST_MPL_ASSERT((is_same<AccumulatorSet, void>)); + + typedef + accumulator_wrapper< + typename mpl::apply2<typename Feature::impl, Sample, Weight>::type + , Feature + > + accumulator_type; + + typedef + typename mpl::if_< + typename Feature::is_weight_accumulator + , accumulator_wrapper<impl::external_impl<accumulator_type, tag::weights>, Feature> + , accumulator_type + >::type + type; + }; + + // BUGBUG work around an MPL bug wrt map insertion + template<typename FeatureMap, typename Feature> + struct insert_feature + : mpl::eval_if< + mpl::has_key<FeatureMap, typename feature_of<Feature>::type> + , mpl::identity<FeatureMap> + , mpl::insert<FeatureMap, mpl::pair<typename feature_of<Feature>::type, Feature> > + > + { + }; + + template<typename FeatureMap, typename Feature, typename Weight> + struct insert_dependencies + : mpl::fold< + as_feature_list<typename Feature::dependencies, Weight> + , FeatureMap + , insert_dependencies< + insert_feature<mpl::_1, mpl::_2> + , mpl::_2 + , Weight + > + > + { + }; + + template<typename FeatureMap, typename Features, typename Weight> + struct insert_sequence + : mpl::fold< // BUGBUG should use insert_range, but doesn't seem to work for maps + as_feature_list<Features, Weight> + , FeatureMap + , insert_feature<mpl::_1, mpl::_2> + > + { + }; + + template<typename Features, typename Sample, typename Weight> + struct make_accumulator_tuple + { + typedef + typename mpl::fold< + as_feature_list<Features, Weight> + , mpl::map0<> + , mpl::if_< + mpl::is_sequence<mpl::_2> + , insert_sequence<mpl::_1, mpl::_2, Weight> + , insert_feature<mpl::_1, mpl::_2> + > + >::type + feature_map; + + // for each element in the map, add its dependencies also + typedef + typename mpl::fold< + feature_map + , feature_map + , insert_dependencies<mpl::_1, mpl::second<mpl::_2>, Weight> + >::type + feature_map_with_dependencies; + + // turn the map into a vector so we can sort it + typedef + typename mpl::insert_range< + mpl::vector<> + , mpl::end<mpl::vector<> >::type + , mpl::transform_view<feature_map_with_dependencies, mpl::second<mpl::_1> > + >::type + feature_vector_with_dependencies; + + // sort the features according to which is derived from which + typedef + typename mpl::sort< + feature_vector_with_dependencies + , is_dependent_on<mpl::_2, mpl::_1> + >::type + sorted_feature_vector; + + // From the vector of features, construct a vector of accumulators + typedef + typename mpl::transform< + sorted_feature_vector + , to_accumulator<mpl::_1, Sample, Weight> + >::type + type; + }; + + } // namespace detail + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/external.hpp b/boost/boost/accumulators/framework/external.hpp new file mode 100644 index 0000000..dbd5d91 --- /dev/null +++ b/boost/boost/accumulators/framework/external.hpp
@@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// external.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTERNAL_HPP_EAN_01_12_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_EXTERNAL_HPP_EAN_01_12_2005 + +#include <boost/mpl/apply.hpp> +#include <boost/accumulators/framework/accumulators/external_accumulator.hpp> + +//namespace boost { namespace accumulators +//{ +// +///////////////////////////////////////////////////////////////////////////////// +//// external +//// +//template<typename Type> +//struct external +//{ +//}; +// +//}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/extractor.hpp b/boost/boost/accumulators/framework/extractor.hpp new file mode 100644 index 0000000..98281ce --- /dev/null +++ b/boost/boost/accumulators/framework/extractor.hpp
@@ -0,0 +1,229 @@ +/////////////////////////////////////////////////////////////////////////////// +// extractor.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_EXTRACTOR_HPP_EAN_28_10_2005 + +#include <boost/preprocessor/tuple/rem.hpp> +#include <boost/preprocessor/array/size.hpp> +#include <boost/preprocessor/array/data.hpp> +#include <boost/preprocessor/array/elem.hpp> +#include <boost/preprocessor/seq/to_array.hpp> +#include <boost/preprocessor/seq/transform.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> +#include <boost/parameter/binding.hpp> +#include <boost/mpl/apply.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> +#include <boost/accumulators/framework/parameters/accumulator.hpp> + +namespace boost { namespace accumulators +{ + +namespace detail +{ + template<typename AccumulatorSet, typename Feature> + struct accumulator_set_result + { + typedef typename as_feature<Feature>::type feature_type; + typedef typename mpl::apply<AccumulatorSet, feature_type>::type::result_type type; + }; + + template<typename Args, typename Feature> + struct argument_pack_result + : accumulator_set_result< + typename remove_reference< + typename parameter::binding<Args, tag::accumulator>::type + >::type + , Feature + > + { + }; + + template<typename A, typename Feature> + struct extractor_result + : mpl::eval_if< + detail::is_accumulator_set<A> + , accumulator_set_result<A, Feature> + , argument_pack_result<A, Feature> + > + { + }; + + template<typename Feature, typename AccumulatorSet> + typename extractor_result<AccumulatorSet, Feature>::type + do_extract(AccumulatorSet const &acc, mpl::true_) + { + typedef typename as_feature<Feature>::type feature_type; + return extract_result<feature_type>(acc); + } + + template<typename Feature, typename Args> + typename extractor_result<Args, Feature>::type + do_extract(Args const &args, mpl::false_) + { + typedef typename as_feature<Feature>::type feature_type; + return find_accumulator<feature_type>(args[accumulator]).result(args); + } + +} // namespace detail + + +/////////////////////////////////////////////////////////////////////////////// +/// Extracts the result associated with Feature from the specified accumulator_set. +template<typename Feature> +struct extractor +{ + typedef extractor<Feature> this_type; + + /// The result meta-function for determining the return type of the extractor + template<typename F> + struct result; + + template<typename A1> + struct result<this_type(A1)> + : detail::extractor_result<A1, Feature> + { + }; + + /// Extract the result associated with Feature from the accumulator set + /// \param acc The accumulator set object from which to extract the result + template<typename Arg1> + typename detail::extractor_result<Arg1, Feature>::type + operator ()(Arg1 const &arg1) const + { + // Arg1 could be an accumulator_set or an argument pack containing + // an accumulator_set. Dispatch accordingly. + return detail::do_extract<Feature>(arg1, detail::is_accumulator_set<Arg1>()); + } + + /// \overload + /// + /// \param a1 Optional named parameter to be passed to the accumulator's result() function. + template<typename AccumulatorSet, typename A1> + typename detail::extractor_result<AccumulatorSet, Feature>::type + operator ()(AccumulatorSet const &acc, A1 const &a1) const + { + BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>)); + typedef typename as_feature<Feature>::type feature_type; + return extract_result<feature_type>(acc, a1); + } + + // ... other overloads generated by Boost.Preprocessor: + + /// INTERNAL ONLY + /// +#define BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP(z, n, _) \ + template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ + struct result<this_type(BOOST_PP_ENUM_PARAMS_Z(z, n, A))> \ + : detail::extractor_result<A1, Feature> \ + {}; \ + template< \ + typename AccumulatorSet \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ + > \ + typename detail::extractor_result<AccumulatorSet, Feature>::type \ + operator ()( \ + AccumulatorSet const &acc \ + BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) \ + ) const \ + { \ + BOOST_MPL_ASSERT((detail::is_accumulator_set<AccumulatorSet>)); \ + typedef typename as_feature<Feature>::type feature_type; \ + return extract_result<feature_type>(acc BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a));\ + } + + BOOST_PP_REPEAT_FROM_TO( + 2 + , BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) + , BOOST_ACCUMULATORS_EXTRACTOR_FUN_OP + , _ + ) + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// \overload + /// + template<typename AccumulatorSet, typename A1, typename A2, ...> + typename detail::extractor_result<AccumulatorSet, Feature>::type + operator ()(AccumulatorSet const &acc, A1 const &a1, A2 const &a2, ...); + #endif +}; + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_ARRAY_REM(Array) \ + BOOST_PP_TUPLE_REM_CTOR(BOOST_PP_ARRAY_SIZE(Array), BOOST_PP_ARRAY_DATA(Array)) + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_SEQ_REM(Seq) \ + BOOST_ACCUMULATORS_ARRAY_REM(BOOST_PP_SEQ_TO_ARRAY(Seq)) + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_ARGS_OP(s, data, elem) \ + T ## s + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_PARAMS_OP(s, data, elem) \ + elem T ## s + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ + Tag::Feature< \ + BOOST_ACCUMULATORS_SEQ_REM( \ + BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_ARGS_OP, ~, ParamsSeq) \ + ) \ + > + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL(z, n, Tag, Feature, ParamsSeq) \ + template< \ + BOOST_ACCUMULATORS_SEQ_REM( \ + BOOST_PP_SEQ_TRANSFORM(BOOST_ACCUMULATORS_PARAMS_OP, ~, ParamsSeq) \ + ) \ + , typename Arg1 \ + BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, typename A) \ + > \ + typename boost::accumulators::detail::extractor_result< \ + Arg1 \ + , BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) \ + >::type \ + Feature(Arg1 const &arg1 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, A, const &a) ) \ + { \ + typedef BOOST_ACCUMULATORS_MAKE_FEATURE(Tag, Feature, ParamsSeq) feature_type; \ + return boost::accumulators::extractor<feature_type>()( \ + arg1 BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)); \ + } + +/// INTERNAL ONLY +/// +#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN(z, n, _) \ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN_IMPL( \ + z \ + , n \ + , BOOST_PP_ARRAY_ELEM(0, _) \ + , BOOST_PP_ARRAY_ELEM(1, _) \ + , BOOST_PP_ARRAY_ELEM(2, _) \ + ) + +#define BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(Tag, Feature, ParamSeq) \ + BOOST_PP_REPEAT( \ + BOOST_PP_INC(BOOST_ACCUMULATORS_MAX_ARGS) \ + , BOOST_ACCUMULATORS_DEFINE_EXTRACTOR_FUN \ + , (3, (Tag, Feature, ParamSeq)) \ + ) + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/features.hpp b/boost/boost/accumulators/framework/features.hpp new file mode 100644 index 0000000..21cae00 --- /dev/null +++ b/boost/boost/accumulators/framework/features.hpp
@@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +// features.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_08_12_2005 +#define BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_08_12_2005 + +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// features +// +template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)> +struct features + : mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/parameters/accumulator.hpp b/boost/boost/accumulators/framework/parameters/accumulator.hpp new file mode 100644 index 0000000..525ebb3 --- /dev/null +++ b/boost/boost/accumulators/framework/parameters/accumulator.hpp
@@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////////////////////// +// accumulator.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_ACCUMULATOR_HPP_EAN_31_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_ACCUMULATOR_HPP_EAN_31_10_2005 + +#include <boost/parameter/keyword.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> + +namespace boost { namespace accumulators +{ + +BOOST_PARAMETER_KEYWORD(tag, accumulator) +BOOST_ACCUMULATORS_IGNORE_GLOBAL(accumulator) + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/parameters/sample.hpp b/boost/boost/accumulators/framework/parameters/sample.hpp new file mode 100644 index 0000000..8b227eb --- /dev/null +++ b/boost/boost/accumulators/framework/parameters/sample.hpp
@@ -0,0 +1,22 @@ +/////////////////////////////////////////////////////////////////////////////// +// sample.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_SAMPLE_HPP_EAN_31_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_SAMPLE_HPP_EAN_31_10_2005 + +#include <boost/parameter/keyword.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> + +namespace boost { namespace accumulators +{ + +BOOST_PARAMETER_KEYWORD(tag, sample) +BOOST_ACCUMULATORS_IGNORE_GLOBAL(sample) + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/parameters/weight.hpp b/boost/boost/accumulators/framework/parameters/weight.hpp new file mode 100644 index 0000000..f36016f --- /dev/null +++ b/boost/boost/accumulators/framework/parameters/weight.hpp
@@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// weight.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHT_HPP_EAN_31_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHT_HPP_EAN_31_10_2005 + +#include <boost/parameter/keyword.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> + +namespace boost { namespace accumulators +{ + +// The weight of a single sample +BOOST_PARAMETER_KEYWORD(tag, weight) +BOOST_ACCUMULATORS_IGNORE_GLOBAL(weight) + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/framework/parameters/weights.hpp b/boost/boost/accumulators/framework/parameters/weights.hpp new file mode 100644 index 0000000..6beae61 --- /dev/null +++ b/boost/boost/accumulators/framework/parameters/weights.hpp
@@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// weights.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHTS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_FRAMEWORK_PARAMETERS_WEIGHTS_HPP_EAN_28_10_2005 + +#include <boost/parameter/keyword.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> + +namespace boost { namespace accumulators +{ + +// The weight accumulator +BOOST_PARAMETER_KEYWORD(tag, weights) +BOOST_ACCUMULATORS_IGNORE_GLOBAL(weights) + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/numeric/detail/function1.hpp b/boost/boost/accumulators/numeric/detail/function1.hpp new file mode 100644 index 0000000..282eb1e --- /dev/null +++ b/boost/boost/accumulators/numeric/detail/function1.hpp
@@ -0,0 +1,75 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_FUNCTION1_DWA200655_HPP +# define BOOST_DETAIL_FUNCTION1_DWA200655_HPP + +# include <boost/concept_check.hpp> +# include <boost/type_traits/remove_reference.hpp> +# include <boost/type_traits/add_const.hpp> +# include <boost/mpl/apply.hpp> + +namespace boost { namespace detail { + +// A utility for creating unary function objects that play nicely with +// boost::result_of and that handle the forwarding problem. +// +// mpl::apply<F, A0>::type is expected to be a stateless function +// object that accepts an argument of type A0&. It is also expected +// to have a nested ::result_type identical to its return type. +template<typename F> +struct function1 +{ + template<typename Signature> + struct result + {}; + + template<typename This, typename A0> + struct result<This(A0)> + { + // How adding const to arguments handles rvalues. + // + // if A0 is arg0 is represents actual argument + // -------- ------- -------------------------- + // T const & T const const T lvalue + // T & T non-const T lvalue + // T const T const const T rvalue + // T T const non-const T rvalue + typedef typename remove_reference< + typename add_const< A0 >::type + >::type arg0; + + typedef typename mpl::apply1<F, arg0>::type impl; + typedef typename impl::result_type type; + }; + + // Handles mutable lvalues + template<typename A0> + typename result<function1(A0 &)>::type + operator ()(A0 &a0) const + { + typedef typename result<function1(A0 &)>::impl impl; + typedef typename result<function1(A0 &)>::type type; + typedef A0 &arg0; + BOOST_CONCEPT_ASSERT((UnaryFunction<impl, type, arg0>)); + //boost::function_requires<UnaryFunctionConcept<impl, type, arg0> >(); + return impl()(a0); + } + + // Handles const lvalues and all rvalues + template<typename A0> + typename result<function1(A0 const &)>::type + operator ()(A0 const &a0) const + { + typedef typename result<function1(A0 const &)>::impl impl; + typedef typename result<function1(A0 const &)>::type type; + typedef A0 const &arg0; + BOOST_CONCEPT_ASSERT((UnaryFunction<impl, type, arg0>)); + //boost::function_requires<UnaryFunctionConcept<impl, type, arg0> >(); + return impl()(a0); + } +}; + +}} // namespace boost::detail + +#endif // BOOST_DETAIL_FUNCTION1_DWA200655_HPP
diff --git a/boost/boost/accumulators/numeric/detail/function2.hpp b/boost/boost/accumulators/numeric/detail/function2.hpp new file mode 100644 index 0000000..daf3c4d --- /dev/null +++ b/boost/boost/accumulators/numeric/detail/function2.hpp
@@ -0,0 +1,10 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_FUNCTION2_DWA200655_HPP +# define BOOST_DETAIL_FUNCTION2_DWA200655_HPP + +# define args (2) +# include <boost/accumulators/numeric/detail/function_n.hpp> + +#endif // BOOST_DETAIL_FUNCTION2_DWA200655_HPP
diff --git a/boost/boost/accumulators/numeric/detail/function3.hpp b/boost/boost/accumulators/numeric/detail/function3.hpp new file mode 100644 index 0000000..175e4d5 --- /dev/null +++ b/boost/boost/accumulators/numeric/detail/function3.hpp
@@ -0,0 +1,10 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_FUNCTION3_DWA2006514_HPP +# define BOOST_DETAIL_FUNCTION3_DWA2006514_HPP + +# define args (3) +# include <boost/accumulators/numeric/detail/function_n.hpp> + +#endif // BOOST_DETAIL_FUNCTION3_DWA2006514_HPP
diff --git a/boost/boost/accumulators/numeric/detail/function4.hpp b/boost/boost/accumulators/numeric/detail/function4.hpp new file mode 100644 index 0000000..a0d7108 --- /dev/null +++ b/boost/boost/accumulators/numeric/detail/function4.hpp
@@ -0,0 +1,10 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_FUNCTION4_DWA2006514_HPP +# define BOOST_DETAIL_FUNCTION4_DWA2006514_HPP + +# define args (4) +# include <boost/accumulators/numeric/detail/function_n.hpp> + +#endif // BOOST_DETAIL_FUNCTION4_DWA2006514_HPP
diff --git a/boost/boost/accumulators/numeric/detail/function_n.hpp b/boost/boost/accumulators/numeric/detail/function_n.hpp new file mode 100644 index 0000000..47c42ed --- /dev/null +++ b/boost/boost/accumulators/numeric/detail/function_n.hpp
@@ -0,0 +1,148 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// #include guards intentionally disabled. +// #ifndef BOOST_DETAIL_FUNCTION_N_DWA2006514_HPP +// # define BOOST_DETAIL_FUNCTION_N_DWA2006514_HPP + +#include <boost/mpl/void.hpp> +#include <boost/mpl/apply.hpp> + +#include <boost/preprocessor/control/if.hpp> +#include <boost/preprocessor/cat.hpp> +#include <boost/preprocessor/punctuation/comma_if.hpp> +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_params.hpp> +#include <boost/preprocessor/repetition/repeat.hpp> +#include <boost/preprocessor/seq/fold_left.hpp> +#include <boost/preprocessor/seq/seq.hpp> +#include <boost/preprocessor/seq/for_each.hpp> +#include <boost/preprocessor/seq/for_each_i.hpp> +#include <boost/preprocessor/seq/for_each_product.hpp> +#include <boost/preprocessor/seq/size.hpp> +#include <boost/type_traits/add_const.hpp> +#include <boost/type_traits/remove_reference.hpp> + +namespace boost { namespace detail { + +# define BOOST_DETAIL_default_arg(z, n, _) \ + typedef mpl::void_ BOOST_PP_CAT(arg, n); + +# define BOOST_DETAIL_function_arg(z, n, _) \ + typedef typename remove_reference< \ + typename add_const< BOOST_PP_CAT(A, n) >::type \ + >::type BOOST_PP_CAT(arg, n); + +#define BOOST_DETAIL_cat_arg_counts(s, state, n) \ + BOOST_PP_IF( \ + n \ + , BOOST_PP_CAT(state, BOOST_PP_CAT(_, n)) \ + , state \ + ) \ + /**/ + +#define function_name \ + BOOST_PP_SEQ_FOLD_LEFT( \ + BOOST_DETAIL_cat_arg_counts \ + , BOOST_PP_CAT(function, BOOST_PP_SEQ_HEAD(args)) \ + , BOOST_PP_SEQ_TAIL(args)(0) \ + ) \ + /**/ + +template<typename F> +struct function_name +{ + BOOST_PP_REPEAT( + BOOST_MPL_LIMIT_METAFUNCTION_ARITY + , BOOST_DETAIL_default_arg + , ~ + ) + + template<typename Signature> + struct result {}; + +#define BOOST_DETAIL_function_result(r, _, n) \ + template<typename This BOOST_PP_ENUM_TRAILING_PARAMS(n, typename A)> \ + struct result<This(BOOST_PP_ENUM_PARAMS(n, A))> \ + { \ + BOOST_PP_REPEAT(n, BOOST_DETAIL_function_arg, ~) \ + typedef \ + typename BOOST_PP_CAT(mpl::apply, BOOST_MPL_LIMIT_METAFUNCTION_ARITY)<\ + F \ + BOOST_PP_ENUM_TRAILING_PARAMS( \ + BOOST_MPL_LIMIT_METAFUNCTION_ARITY \ + , arg \ + ) \ + >::type \ + impl; \ + typedef typename impl::result_type type; \ + }; \ + /**/ + + BOOST_PP_SEQ_FOR_EACH(BOOST_DETAIL_function_result, _, args) + +# define arg_type(r, _, i, is_const) \ + BOOST_PP_COMMA_IF(i) BOOST_PP_CAT(A, i) BOOST_PP_CAT(const_if, is_const) & + +# define result_(r, n, constness) \ + typename result< \ + function_name( \ + BOOST_PP_SEQ_FOR_EACH_I_R(r, arg_type, ~, constness) \ + ) \ + > \ + /**/ + +# define param(r, _, i, is_const) BOOST_PP_COMMA_IF(i) \ + BOOST_PP_CAT(A, i) BOOST_PP_CAT(const_if, is_const) & BOOST_PP_CAT(x, i) + +# define param_list(r, n, constness) \ + BOOST_PP_SEQ_FOR_EACH_I_R(r, param, ~, constness) + +# define call_operator(r, constness) \ + template<BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(constness), typename A)> \ + result_(r, BOOST_PP_SEQ_SIZE(constness), constness)::type \ + operator ()( param_list(r, BOOST_PP_SEQ_SIZE(constness), constness) ) const \ + { \ + typedef result_(r, BOOST_PP_SEQ_SIZE(constness), constness)::impl impl; \ + return impl()(BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(constness), x)); \ + } \ + /**/ + +# define const_if0 +# define const_if1 const + +# define bits(z, n, _) ((0)(1)) + +# define gen_operator(r, _, n) \ + BOOST_PP_SEQ_FOR_EACH_PRODUCT_R( \ + r \ + , call_operator \ + , BOOST_PP_REPEAT(n, bits, ~) \ + ) \ + /**/ + + BOOST_PP_SEQ_FOR_EACH( + gen_operator + , ~ + , args + ) + +# undef bits +# undef const_if1 +# undef const_if0 +# undef call_operator +# undef param_list +# undef param +# undef result_ +# undef default_ +# undef arg_type +# undef gen_operator +# undef function_name + +# undef args +}; + +}} // namespace boost::detail + +//#endif // BOOST_DETAIL_FUNCTION_N_DWA2006514_HPP
diff --git a/boost/boost/accumulators/numeric/detail/pod_singleton.hpp b/boost/boost/accumulators/numeric/detail/pod_singleton.hpp new file mode 100644 index 0000000..317d85f --- /dev/null +++ b/boost/boost/accumulators/numeric/detail/pod_singleton.hpp
@@ -0,0 +1,20 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_DETAIL_POD_SINGLETON_DWA200655_HPP +# define BOOST_DETAIL_POD_SINGLETON_DWA200655_HPP + +namespace boost { namespace detail { + +template<typename T> +struct pod_singleton +{ + static T instance; +}; + +template<typename T> +T pod_singleton<T>::instance; + +}} // namespace boost::detail + +#endif // BOOST_DETAIL_POD_SINGLETON_DWA200655_HPP
diff --git a/boost/boost/accumulators/numeric/functional.hpp b/boost/boost/accumulators/numeric/functional.hpp new file mode 100644 index 0000000..d5d79f5 --- /dev/null +++ b/boost/boost/accumulators/numeric/functional.hpp
@@ -0,0 +1,521 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file functional.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005 +#define BOOST_NUMERIC_FUNCTIONAL_HPP_EAN_08_12_2005 + +#include <limits> +#include <functional> +#include <boost/static_assert.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/and.hpp> +#include <boost/type_traits/remove_const.hpp> +#include <boost/type_traits/add_reference.hpp> +#include <boost/type_traits/is_empty.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/is_floating_point.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/typeof/typeof.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> +#include <boost/accumulators/numeric/functional_fwd.hpp> +#include <boost/accumulators/numeric/detail/function1.hpp> +#include <boost/accumulators/numeric/detail/function2.hpp> +#include <boost/accumulators/numeric/detail/pod_singleton.hpp> + +#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VECTOR_SUPPORT +# include <boost/accumulators/numeric/functional/vector.hpp> +#endif + +#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_VALARRAY_SUPPORT +# include <boost/accumulators/numeric/functional/valarray.hpp> +#endif + +#ifdef BOOST_NUMERIC_FUNCTIONAL_STD_COMPLEX_SUPPORT +# include <boost/accumulators/numeric/functional/complex.hpp> +#endif + +/// INTERNAL ONLY +/// +#define BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED + +#ifdef BOOST_NUMERIC_FUNCTIONAL_DOXYGEN_INVOKED +// Hack to make Doxygen show the inheritance relationships +/// INTERNAL ONLY +/// +namespace std +{ + /// INTERNAL ONLY + /// + template<class Arg, class Ret> struct unary_function {}; + /// INTERNAL ONLY + /// + template<class Left, class Right, class Ret> struct binary_function {}; +} +#endif + +namespace boost { namespace numeric +{ + namespace functional + { + /// INTERNAL ONLY + /// + template<typename A0, typename A1> + struct are_integral + : mpl::and_<is_integral<A0>, is_integral<A1> > + {}; + + template<typename Left, typename Right> + struct left_ref + { + typedef Left &type; + }; + + namespace detail + { + template<typename T> + T &lvalue_of(); + } + } + + // TODO: handle complex weight, valarray, MTL vectors + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(Name, Op) \ + namespace functional \ + { \ + template<typename Arg> \ + struct result_of_ ## Name \ + { \ + BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \ + nested \ + , Op boost::numeric::functional::detail::lvalue_of<Arg>() \ + ) \ + typedef typename nested::type type; \ + }; \ + template<typename Arg, typename EnableIf> \ + struct Name ## _base \ + : std::unary_function< \ + typename remove_const<Arg>::type \ + , typename result_of_ ## Name<Arg>::type \ + > \ + { \ + typename result_of_ ## Name<Arg>::type operator ()(Arg &arg) const \ + { \ + return Op arg; \ + } \ + }; \ + template<typename Arg, typename ArgTag> \ + struct Name \ + : Name ## _base<Arg, void> \ + {}; \ + } \ + namespace op \ + { \ + struct Name \ + : boost::detail::function1<functional::Name<_, functional::tag<_> > > \ + {}; \ + } \ + namespace \ + { \ + op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance; \ + } \ + /**/ + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(Name, Op, RetType) \ + namespace functional \ + { \ + template<typename Left, typename Right, typename EnableIf> \ + struct result_of_ ## Name \ + { \ + RetType(Left, Op, Right) \ + }; \ + template<typename Left, typename Right, typename EnableIf> \ + struct Name ## _base \ + : std::binary_function< \ + typename remove_const<Left>::type \ + , typename remove_const<Right>::type \ + , typename result_of_ ## Name<Left, Right>::type \ + > \ + { \ + typename result_of_ ## Name<Left, Right>::type \ + operator ()(Left &left, Right &right) const \ + { \ + return left Op right; \ + } \ + }; \ + template<typename Left, typename Right, typename LeftTag, typename RightTag> \ + struct Name \ + : Name ## _base<Left, Right, void> \ + {}; \ + } \ + namespace op \ + { \ + struct Name \ + : boost::detail::function2< \ + functional::Name<_1, _2, functional::tag<_1>, functional::tag<_2> > \ + > \ + {}; \ + } \ + namespace \ + { \ + op::Name const &Name = boost::detail::pod_singleton<op::Name>::instance; \ + } \ + BOOST_ACCUMULATORS_IGNORE_GLOBAL(Name) \ + /**/ + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DEDUCED(Left, Op, Right) \ + BOOST_TYPEOF_NESTED_TYPEDEF_TPL( \ + nested \ + , boost::numeric::functional::detail::lvalue_of<Left>() Op \ + boost::numeric::functional::detail::lvalue_of<Right>() \ + ) \ + typedef typename nested::type type; \ + /**/ + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_LEFT(Left, Op, Right) \ + typedef Left &type; \ + /**/ + + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus, +, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus, -, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies, *, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides, /, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus, %, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater, >, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(greater_equal, >=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less, <, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(less_equal, <=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(equal_to, ==, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(not_equal_to, !=, BOOST_NUMERIC_FUNCTIONAL_DEDUCED) + + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(assign, =, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(plus_assign, +=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(minus_assign, -=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(multiplies_assign, *=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(divides_assign, /=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP(modulus_assign, %=, BOOST_NUMERIC_FUNCTIONAL_LEFT) + + BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_plus, +) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(unary_minus, -) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(complement, ~) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP(logical_not, !) + +#undef BOOST_NUMERIC_FUNCTIONAL_LEFT +#undef BOOST_NUMERIC_FUNCTIONAL_DEDUCED +#undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_UNARY_OP +#undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_BINARY_OP + + namespace functional + { + template<typename Left, typename Right, typename EnableIf> + struct min_assign_base + : std::binary_function<Left, Right, void> + { + void operator ()(Left &left, Right &right) const + { + if(numeric::less(right, left)) + { + left = right; + } + } + }; + + template<typename Left, typename Right, typename EnableIf> + struct max_assign_base + : std::binary_function<Left, Right, void> + { + void operator ()(Left &left, Right &right) const + { + if(numeric::greater(right, left)) + { + left = right; + } + } + }; + + template<typename Left, typename Right, typename EnableIf> + struct fdiv_base + : functional::divides<Left, Right> + {}; + + // partial specialization that promotes the arguments to double for + // integral division. + template<typename Left, typename Right> + struct fdiv_base<Left, Right, typename enable_if<are_integral<Left, Right> >::type> + : functional::divides<double const, double const> + {}; + + template<typename To, typename From, typename EnableIf> + struct promote_base + : std::unary_function<From, To> + { + To operator ()(From &from) const + { + return from; + } + }; + + template<typename ToFrom> + struct promote_base<ToFrom, ToFrom, void> + : std::unary_function<ToFrom, ToFrom> + { + ToFrom &operator ()(ToFrom &tofrom) + { + return tofrom; + } + }; + + template<typename Arg, typename EnableIf> + struct as_min_base + : std::unary_function<Arg, typename remove_const<Arg>::type> + { + BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized); + + typename remove_const<Arg>::type operator ()(Arg &) const + { + return (std::numeric_limits<typename remove_const<Arg>::type>::min)(); + } + }; + + template<typename Arg> + struct as_min_base<Arg, typename enable_if<is_floating_point<Arg> >::type> + : std::unary_function<Arg, typename remove_const<Arg>::type> + { + BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized); + + typename remove_const<Arg>::type operator ()(Arg &) const + { + return -(std::numeric_limits<typename remove_const<Arg>::type>::max)(); + } + }; + + template<typename Arg, typename EnableIf> + struct as_max_base + : std::unary_function<Arg, typename remove_const<Arg>::type> + { + BOOST_STATIC_ASSERT(std::numeric_limits<typename remove_const<Arg>::type>::is_specialized); + + typename remove_const<Arg>::type operator ()(Arg &) const + { + return (std::numeric_limits<typename remove_const<Arg>::type>::max)(); + } + }; + + template<typename Arg, typename EnableIf> + struct as_zero_base + : std::unary_function<Arg, typename remove_const<Arg>::type> + { + typename remove_const<Arg>::type operator ()(Arg &) const + { + return numeric::zero<typename remove_const<Arg>::type>::value; + } + }; + + template<typename Arg, typename EnableIf> + struct as_one_base + : std::unary_function<Arg, typename remove_const<Arg>::type> + { + typename remove_const<Arg>::type operator ()(Arg &) const + { + return numeric::one<typename remove_const<Arg>::type>::value; + } + }; + + template<typename To, typename From, typename ToTag, typename FromTag> + struct promote + : promote_base<To, From, void> + {}; + + template<typename Left, typename Right, typename LeftTag, typename RightTag> + struct min_assign + : min_assign_base<Left, Right, void> + {}; + + template<typename Left, typename Right, typename LeftTag, typename RightTag> + struct max_assign + : max_assign_base<Left, Right, void> + {}; + + template<typename Left, typename Right, typename LeftTag, typename RightTag> + struct fdiv + : fdiv_base<Left, Right, void> + {}; + + /// INTERNAL ONLY + /// For back-compat only. Use fdiv. + template<typename Left, typename Right, typename LeftTag, typename RightTag> + struct average + : fdiv<Left, Right, LeftTag, RightTag> + {}; + + template<typename Arg, typename Tag> + struct as_min + : as_min_base<Arg, void> + {}; + + template<typename Arg, typename Tag> + struct as_max + : as_max_base<Arg, void> + {}; + + template<typename Arg, typename Tag> + struct as_zero + : as_zero_base<Arg, void> + {}; + + template<typename Arg, typename Tag> + struct as_one + : as_one_base<Arg, void> + {}; + } + + namespace op + { + template<typename To> + struct promote + : boost::detail::function1<functional::promote<To, _, typename functional::tag<To>::type, functional::tag<_> > > + {}; + + struct min_assign + : boost::detail::function2<functional::min_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > > + {}; + + struct max_assign + : boost::detail::function2<functional::max_assign<_1, _2, functional::tag<_1>, functional::tag<_2> > > + {}; + + struct fdiv + : boost::detail::function2<functional::fdiv<_1, _2, functional::tag<_1>, functional::tag<_2> > > + {}; + + /// INTERNAL ONLY + struct average + : boost::detail::function2<functional::fdiv<_1, _2, functional::tag<_1>, functional::tag<_2> > > + {}; + + struct as_min + : boost::detail::function1<functional::as_min<_, functional::tag<_> > > + {}; + + struct as_max + : boost::detail::function1<functional::as_max<_, functional::tag<_> > > + {}; + + struct as_zero + : boost::detail::function1<functional::as_zero<_, functional::tag<_> > > + {}; + + struct as_one + : boost::detail::function1<functional::as_one<_, functional::tag<_> > > + {}; + } + + namespace + { + op::min_assign const &min_assign = boost::detail::pod_singleton<op::min_assign>::instance; + op::max_assign const &max_assign = boost::detail::pod_singleton<op::max_assign>::instance; + op::fdiv const &fdiv = boost::detail::pod_singleton<op::fdiv>::instance; + op::fdiv const &average = boost::detail::pod_singleton<op::fdiv>::instance; ///< INTERNAL ONLY + op::as_min const &as_min = boost::detail::pod_singleton<op::as_min>::instance; + op::as_max const &as_max = boost::detail::pod_singleton<op::as_max>::instance; + op::as_zero const &as_zero = boost::detail::pod_singleton<op::as_zero>::instance; + op::as_one const &as_one = boost::detail::pod_singleton<op::as_one>::instance; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(min_assign) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(max_assign) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(fdiv) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(average) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_min) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_max) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_zero) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(as_one) + } + + /////////////////////////////////////////////////////////////////////////////// + // promote + template<typename To, typename From> + typename lazy_disable_if<is_const<From>, mpl::if_<is_same<To, From>, To &, To> >::type + promote(From &from) + { + return functional::promote<To, From>()(from); + } + + template<typename To, typename From> + typename mpl::if_<is_same<To const, From const>, To const &, To const>::type + promote(From const &from) + { + return functional::promote<To const, From const>()(from); + } + + template<typename T> + struct default_ + { + typedef default_ type; + typedef T value_type; + static T const value; + + operator T const & () const + { + return default_::value; + } + }; + + template<typename T> + T const default_<T>::value = T(); + + template<typename T> + struct one + { + typedef one type; + typedef T value_type; + static T const value; + + operator T const & () const + { + return one::value; + } + }; + + template<typename T> + T const one<T>::value = T(1); + + template<typename T> + struct zero + { + typedef zero type; + typedef T value_type; + static T const value; + + operator T const & () const + { + return zero::value; + } + }; + + template<typename T> + T const zero<T>::value = T(); + + template<typename T> + struct one_or_default + : mpl::if_<is_empty<T>, default_<T>, one<T> >::type + {}; + + template<typename T> + struct zero_or_default + : mpl::if_<is_empty<T>, default_<T>, zero<T> >::type + {}; + +}} // namespace boost::numeric + +#endif
diff --git a/boost/boost/accumulators/numeric/functional/complex.hpp b/boost/boost/accumulators/numeric/functional/complex.hpp new file mode 100644 index 0000000..ea8c033 --- /dev/null +++ b/boost/boost/accumulators/numeric/functional/complex.hpp
@@ -0,0 +1,82 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file complex.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_COMPLEX_HPP_EAN_01_17_2006 +#define BOOST_NUMERIC_FUNCTIONAL_COMPLEX_HPP_EAN_01_17_2006 + +#ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED +# error Include this file before boost/accumulators/numeric/functional.hpp +#endif + +#include <complex> +#include <boost/mpl/or.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/typeof/std/complex.hpp> +#include <boost/accumulators/numeric/functional_fwd.hpp> + +namespace boost { namespace numeric { namespace operators +{ + // So that the stats compile when Sample type is std::complex + template<typename T, typename U> + typename + disable_if< + mpl::or_<is_same<T, U>, is_same<std::complex<T>, U> > + , std::complex<T> + >::type + operator *(std::complex<T> ri, U const &u) + { + // BUGBUG promote result to typeof(T()*u) ? + return ri *= static_cast<T>(u); + } + + template<typename T, typename U> + typename + disable_if< + mpl::or_<is_same<T, U>, is_same<std::complex<T>, U> > + , std::complex<T> + >::type + operator /(std::complex<T> ri, U const &u) + { + // BUGBUG promote result to typeof(T()*u) ? + return ri /= static_cast<T>(u); + } + +}}} // namespace boost::numeric::operators + +namespace boost { namespace numeric +{ + namespace detail + { + template<typename T> + struct one_complex + { + static std::complex<T> const value; + }; + + template<typename T> + std::complex<T> const one_complex<T>::value + = std::complex<T>(numeric::one<T>::value, numeric::one<T>::value); + } + + /// INTERNAL ONLY + /// + template<typename T> + struct one<std::complex<T> > + : detail::one_complex<T> + { + typedef one type; + typedef std::complex<T> value_type; + operator value_type const & () const + { + return detail::one_complex<T>::value; + } + }; + +}} // namespace boost::numeric + +#endif
diff --git a/boost/boost/accumulators/numeric/functional/valarray.hpp b/boost/boost/accumulators/numeric/functional/valarray.hpp new file mode 100644 index 0000000..c24b458 --- /dev/null +++ b/boost/boost/accumulators/numeric/functional/valarray.hpp
@@ -0,0 +1,360 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file valarray.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005 +#define BOOST_NUMERIC_FUNCTIONAL_VALARRAY_HPP_EAN_12_12_2005 + +#ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED +# error Include this file before boost/accumulators/numeric/functional.hpp +#endif + +#include <valarray> +#include <functional> +#include <boost/assert.hpp> +#include <boost/mpl/and.hpp> +#include <boost/mpl/not.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_scalar.hpp> +#include <boost/type_traits/remove_const.hpp> +#include <boost/typeof/std/valarray.hpp> +#include <boost/accumulators/numeric/functional_fwd.hpp> + +namespace boost { namespace numeric +{ + namespace operators + { + namespace acc_detail + { + template<typename Fun> + struct make_valarray + { + typedef std::valarray<typename Fun::result_type> type; + }; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle valarray<Left> / Right where Right is a scalar and Right != Left. + template<typename Left, typename Right> + typename lazy_enable_if< + mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > > + , acc_detail::make_valarray<functional::divides<Left, Right> > + >::type + operator /(std::valarray<Left> const &left, Right const &right) + { + typedef typename functional::divides<Left, Right>::result_type value_type; + std::valarray<value_type> result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::divides(left[i], right); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle valarray<Left> * Right where Right is a scalar and Right != Left. + template<typename Left, typename Right> + typename lazy_enable_if< + mpl::and_<is_scalar<Right>, mpl::not_<is_same<Left, Right> > > + , acc_detail::make_valarray<functional::multiplies<Left, Right> > + >::type + operator *(std::valarray<Left> const &left, Right const &right) + { + typedef typename functional::multiplies<Left, Right>::result_type value_type; + std::valarray<value_type> result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::multiplies(left[i], right); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle valarray<Left> + valarray<Right> where Right != Left. + template<typename Left, typename Right> + typename lazy_disable_if< + is_same<Left, Right> + , acc_detail::make_valarray<functional::plus<Left, Right> > + >::type + operator +(std::valarray<Left> const &left, std::valarray<Right> const &right) + { + typedef typename functional::plus<Left, Right>::result_type value_type; + std::valarray<value_type> result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::plus(left[i], right[i]); + } + return result; + } + } + + namespace functional + { + struct std_valarray_tag; + + template<typename T> + struct tag<std::valarray<T> > + { + typedef std_valarray_tag type; + }; + + #ifdef __GLIBCXX__ + template<typename T, typename U> + struct tag<std::_Expr<T, U> > + { + typedef std_valarray_tag type; + }; + #endif + + /// INTERNAL ONLY + /// + // This is necessary because the GCC stdlib uses expression templates, and + // typeof(som-valarray-expression) is not an instance of std::valarray + #define BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(Name, Op) \ + template<typename Left, typename Right> \ + struct Name<Left, Right, std_valarray_tag, std_valarray_tag> \ + : std::binary_function< \ + Left \ + , Right \ + , std::valarray< \ + typename Name< \ + typename Left::value_type \ + , typename Right::value_type \ + >::result_type \ + > \ + > \ + { \ + typedef typename Left::value_type left_value_type; \ + typedef typename Right::value_type right_value_type; \ + typedef \ + std::valarray< \ + typename Name<left_value_type, right_value_type>::result_type \ + > \ + result_type; \ + result_type \ + operator ()(Left &left, Right &right) const \ + { \ + return numeric::promote<std::valarray<left_value_type> >(left) \ + Op numeric::promote<std::valarray<right_value_type> >(right); \ + } \ + }; \ + template<typename Left, typename Right> \ + struct Name<Left, Right, std_valarray_tag, void> \ + : std::binary_function< \ + Left \ + , Right \ + , std::valarray< \ + typename Name<typename Left::value_type, Right>::result_type \ + > \ + > \ + { \ + typedef typename Left::value_type left_value_type; \ + typedef \ + std::valarray< \ + typename Name<left_value_type, Right>::result_type \ + > \ + result_type; \ + result_type \ + operator ()(Left &left, Right &right) const \ + { \ + return numeric::promote<std::valarray<left_value_type> >(left) Op right;\ + } \ + }; \ + template<typename Left, typename Right> \ + struct Name<Left, Right, void, std_valarray_tag> \ + : std::binary_function< \ + Left \ + , Right \ + , std::valarray< \ + typename Name<Left, typename Right::value_type>::result_type \ + > \ + > \ + { \ + typedef typename Right::value_type right_value_type; \ + typedef \ + std::valarray< \ + typename Name<Left, right_value_type>::result_type \ + > \ + result_type; \ + result_type \ + operator ()(Left &left, Right &right) const \ + { \ + return left Op numeric::promote<std::valarray<right_value_type> >(right);\ + } \ + }; + + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(plus, +) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(minus, -) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(multiplies, *) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(divides, /) + BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP(modulus, %) + + #undef BOOST_NUMERIC_FUNCTIONAL_DEFINE_VALARRAY_BIN_OP + + /////////////////////////////////////////////////////////////////////////////// + // element-wise min of std::valarray + template<typename Left, typename Right> + struct min_assign<Left, Right, std_valarray_tag, std_valarray_tag> + : std::binary_function<Left, Right, void> + { + void operator ()(Left &left, Right &right) const + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + if(numeric::less(right[i], left[i])) + { + left[i] = right[i]; + } + } + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // element-wise max of std::valarray + template<typename Left, typename Right> + struct max_assign<Left, Right, std_valarray_tag, std_valarray_tag> + : std::binary_function<Left, Right, void> + { + void operator ()(Left &left, Right &right) const + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + if(numeric::greater(right[i], left[i])) + { + left[i] = right[i]; + } + } + } + }; + + // partial specialization of numeric::fdiv<> for std::valarray. + template<typename Left, typename Right, typename RightTag> + struct fdiv<Left, Right, std_valarray_tag, RightTag> + : mpl::if_< + are_integral<typename Left::value_type, Right> + , divides<Left, double const> + , divides<Left, Right> + >::type + {}; + + // promote + template<typename To, typename From> + struct promote<To, From, std_valarray_tag, std_valarray_tag> + : std::unary_function<From, To> + { + To operator ()(From &arr) const + { + typename remove_const<To>::type res(arr.size()); + for(std::size_t i = 0, size = arr.size(); i != size; ++i) + { + res[i] = numeric::promote<typename To::value_type>(arr[i]); + } + return res; + } + }; + + template<typename ToFrom> + struct promote<ToFrom, ToFrom, std_valarray_tag, std_valarray_tag> + : std::unary_function<ToFrom, ToFrom> + { + ToFrom &operator ()(ToFrom &tofrom) const + { + return tofrom; + } + }; + + // for "promoting" a std::valarray<bool> to a bool, useful for + // comparing 2 valarrays for equality: + // if(numeric::promote<bool>(a == b)) + template<typename From> + struct promote<bool, From, void, std_valarray_tag> + : std::unary_function<From, bool> + { + bool operator ()(From &arr) const + { + BOOST_MPL_ASSERT((is_same<bool, typename From::value_type>)); + for(std::size_t i = 0, size = arr.size(); i != size; ++i) + { + if(!arr[i]) + { + return false; + } + } + return true; + } + }; + + template<typename From> + struct promote<bool const, From, void, std_valarray_tag> + : promote<bool, From, void, std_valarray_tag> + {}; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_min + template<typename T> + struct as_min<T, std_valarray_tag> + : std::unary_function<T, typename remove_const<T>::type> + { + typename remove_const<T>::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(numeric::as_min(arr[0]), arr.size()); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_max + template<typename T> + struct as_max<T, std_valarray_tag> + : std::unary_function<T, typename remove_const<T>::type> + { + typename remove_const<T>::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(numeric::as_max(arr[0]), arr.size()); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_zero + template<typename T> + struct as_zero<T, std_valarray_tag> + : std::unary_function<T, typename remove_const<T>::type> + { + typename remove_const<T>::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(numeric::as_zero(arr[0]), arr.size()); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_one + template<typename T> + struct as_one<T, std_valarray_tag> + : std::unary_function<T, typename remove_const<T>::type> + { + typename remove_const<T>::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(numeric::as_one(arr[0]), arr.size()); + } + }; + + } // namespace functional + +}} // namespace boost::numeric + +#endif +
diff --git a/boost/boost/accumulators/numeric/functional/vector.hpp b/boost/boost/accumulators/numeric/functional/vector.hpp new file mode 100644 index 0000000..8a68a3f --- /dev/null +++ b/boost/boost/accumulators/numeric/functional/vector.hpp
@@ -0,0 +1,329 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file vector.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005 +#define BOOST_NUMERIC_FUNCTIONAL_VECTOR_HPP_EAN_12_12_2005 + +#ifdef BOOST_NUMERIC_FUNCTIONAL_HPP_INCLUDED +# error Include this file before boost/accumulators/numeric/functional.hpp +#endif + +#include <vector> +#include <functional> +#include <boost/assert.hpp> +#include <boost/mpl/and.hpp> +#include <boost/mpl/not.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_scalar.hpp> +#include <boost/type_traits/remove_const.hpp> +#include <boost/typeof/std/vector.hpp> +#include <boost/accumulators/numeric/functional_fwd.hpp> + +namespace boost { namespace numeric +{ + namespace operators + { + namespace acc_detail + { + template<typename Fun> + struct make_vector + { + typedef std::vector<typename Fun::result_type> type; + }; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector<Left> / Right where Right is a scalar. + template<typename Left, typename Right> + typename lazy_enable_if< + is_scalar<Right> + , acc_detail::make_vector<functional::divides<Left, Right> > + >::type + operator /(std::vector<Left> const &left, Right const &right) + { + typedef typename functional::divides<Left, Right>::result_type value_type; + std::vector<value_type> result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::divides(left[i], right); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector<Left> / vector<Right>. + template<typename Left, typename Right> + std::vector<typename functional::divides<Left, Right>::result_type> + operator /(std::vector<Left> const &left, std::vector<Right> const &right) + { + typedef typename functional::divides<Left, Right>::result_type value_type; + std::vector<value_type> result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::divides(left[i], right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector<Left> * Right where Right is a scalar. + template<typename Left, typename Right> + typename lazy_enable_if< + is_scalar<Right> + , acc_detail::make_vector<functional::multiplies<Left, Right> > + >::type + operator *(std::vector<Left> const &left, Right const &right) + { + typedef typename functional::multiplies<Left, Right>::result_type value_type; + std::vector<value_type> result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::multiplies(left[i], right); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle Left * vector<Right> where Left is a scalar. + template<typename Left, typename Right> + typename lazy_enable_if< + is_scalar<Left> + , acc_detail::make_vector<functional::multiplies<Left, Right> > + >::type + operator *(Left const &left, std::vector<Right> const &right) + { + typedef typename functional::multiplies<Left, Right>::result_type value_type; + std::vector<value_type> result(right.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::multiplies(left, right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector<Left> * vector<Right> + template<typename Left, typename Right> + std::vector<typename functional::multiplies<Left, Right>::result_type> + operator *(std::vector<Left> const &left, std::vector<Right> const &right) + { + typedef typename functional::multiplies<Left, Right>::result_type value_type; + std::vector<value_type> result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::multiplies(left[i], right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector<Left> + vector<Right> + template<typename Left, typename Right> + std::vector<typename functional::plus<Left, Right>::result_type> + operator +(std::vector<Left> const &left, std::vector<Right> const &right) + { + typedef typename functional::plus<Left, Right>::result_type value_type; + std::vector<value_type> result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::plus(left[i], right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector<Left> - vector<Right> + template<typename Left, typename Right> + std::vector<typename functional::minus<Left, Right>::result_type> + operator -(std::vector<Left> const &left, std::vector<Right> const &right) + { + typedef typename functional::minus<Left, Right>::result_type value_type; + std::vector<value_type> result(left.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::minus(left[i], right[i]); + } + return result; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle vector<Left> += vector<Left> + template<typename Left> + std::vector<Left> & + operator +=(std::vector<Left> &left, std::vector<Left> const &right) + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + numeric::plus_assign(left[i], right[i]); + } + return left; + } + + /////////////////////////////////////////////////////////////////////////////// + // Handle -vector<Arg> + template<typename Arg> + std::vector<typename functional::unary_minus<Arg>::result_type> + operator -(std::vector<Arg> const &arg) + { + typedef typename functional::unary_minus<Arg>::result_type value_type; + std::vector<value_type> result(arg.size()); + for(std::size_t i = 0, size = result.size(); i != size; ++i) + { + result[i] = numeric::unary_minus(arg[i]); + } + return result; + } + } + + namespace functional + { + struct std_vector_tag; + + template<typename T, typename Al> + struct tag<std::vector<T, Al> > + { + typedef std_vector_tag type; + }; + + /////////////////////////////////////////////////////////////////////////////// + // element-wise min of std::vector + template<typename Left, typename Right> + struct min_assign<Left, Right, std_vector_tag, std_vector_tag> + : std::binary_function<Left, Right, void> + { + void operator ()(Left &left, Right &right) const + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + if(numeric::less(right[i], left[i])) + { + left[i] = right[i]; + } + } + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // element-wise max of std::vector + template<typename Left, typename Right> + struct max_assign<Left, Right, std_vector_tag, std_vector_tag> + : std::binary_function<Left, Right, void> + { + void operator ()(Left &left, Right &right) const + { + BOOST_ASSERT(left.size() == right.size()); + for(std::size_t i = 0, size = left.size(); i != size; ++i) + { + if(numeric::greater(right[i], left[i])) + { + left[i] = right[i]; + } + } + } + }; + + // partial specialization for std::vector. + template<typename Left, typename Right> + struct fdiv<Left, Right, std_vector_tag, void> + : mpl::if_< + are_integral<typename Left::value_type, Right> + , divides<Left, double const> + , divides<Left, Right> + >::type + {}; + + // promote + template<typename To, typename From> + struct promote<To, From, std_vector_tag, std_vector_tag> + : std::unary_function<From, To> + { + To operator ()(From &arr) const + { + typename remove_const<To>::type res(arr.size()); + for(std::size_t i = 0, size = arr.size(); i != size; ++i) + { + res[i] = numeric::promote<typename To::value_type>(arr[i]); + } + return res; + } + }; + + template<typename ToFrom> + struct promote<ToFrom, ToFrom, std_vector_tag, std_vector_tag> + : std::unary_function<ToFrom, ToFrom> + { + ToFrom &operator ()(ToFrom &tofrom) const + { + return tofrom; + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_min + template<typename T> + struct as_min<T, std_vector_tag> + : std::unary_function<T, typename remove_const<T>::type> + { + typename remove_const<T>::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(arr.size(), numeric::as_min(arr[0])); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_max + template<typename T> + struct as_max<T, std_vector_tag> + : std::unary_function<T, typename remove_const<T>::type> + { + typename remove_const<T>::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(arr.size(), numeric::as_max(arr[0])); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_zero + template<typename T> + struct as_zero<T, std_vector_tag> + : std::unary_function<T, typename remove_const<T>::type> + { + typename remove_const<T>::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(arr.size(), numeric::as_zero(arr[0])); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // functional::as_one + template<typename T> + struct as_one<T, std_vector_tag> + : std::unary_function<T, typename remove_const<T>::type> + { + typename remove_const<T>::type operator ()(T &arr) const + { + return 0 == arr.size() + ? T() + : T(arr.size(), numeric::as_one(arr[0])); + } + }; + + } // namespace functional + +}} // namespace boost::numeric + +#endif +
diff --git a/boost/boost/accumulators/numeric/functional_fwd.hpp b/boost/boost/accumulators/numeric/functional_fwd.hpp new file mode 100644 index 0000000..501f654 --- /dev/null +++ b/boost/boost/accumulators/numeric/functional_fwd.hpp
@@ -0,0 +1,221 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file functional_fwd.hpp +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_NUMERIC_FUNCTIONAL_FWD_HPP_EAN_08_12_2005 +#define BOOST_NUMERIC_FUNCTIONAL_FWD_HPP_EAN_08_12_2005 + +#include <boost/mpl/if.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_const.hpp> + +namespace boost { namespace numeric +{ + // For using directives -- this namespace may be re-opened elsewhere + namespace operators + {} + + namespace op + { + using mpl::_; + using mpl::_1; + using mpl::_2; + } + + namespace functional + { + using namespace operators; + + template<typename T> + struct tag + { + typedef void type; + }; + + template<typename T> + struct tag<T const> + : tag<T> + {}; + + template<typename T> + struct tag<T volatile> + : tag<T> + {}; + + template<typename T> + struct tag<T const volatile> + : tag<T> + {}; + + template<typename T> + struct static_; + + template<typename A0, typename A1> + struct are_integral; + } + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(Name, Op) \ + namespace functional \ + { \ + template<typename Arg, typename EnableIf = void> \ + struct Name ## _base; \ + template<typename Arg, typename ArgTag = typename tag<Arg>::type> \ + struct Name; \ + } \ + namespace op \ + { \ + struct Name; \ + } \ + namespace \ + { \ + extern op::Name const &Name; \ + } + + /// INTERNAL ONLY + /// +#define BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(Name) \ + namespace functional \ + { \ + template<typename Left, typename Right, typename EnableIf = void> \ + struct result_of_ ## Name; \ + template<typename Left, typename Right, typename EnableIf = void> \ + struct Name ## _base; \ + template< \ + typename Left \ + , typename Right \ + , typename LeftTag = typename tag<Left>::type \ + , typename RightTag = typename tag<Right>::type \ + > \ + struct Name; \ + } \ + namespace op \ + { \ + struct Name; \ + } \ + namespace \ + { \ + extern op::Name const &Name; \ + } + + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(plus) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(minus) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(multiplies) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(divides) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(modulus) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(greater) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(greater_equal) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(less) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(less_equal) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(equal_to) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(not_equal_to) + + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(plus_assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(minus_assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(multiplies_assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(divides_assign) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP(modulus_assign) + + BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(unary_plus, +) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(unary_minus, -) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(complement, ~) + BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP(logical_not, !) + +#undef BOOST_NUMERIC_FUNCTIONAL_DECLARE_UNARY_OP +#undef BOOST_NUMERIC_FUNCTIONAL_DECLARE_BINARY_OP + + + namespace functional + { + template<typename To, typename From, typename EnableIf = void> + struct promote_base; + template<typename Left, typename Right, typename EnableIf = void> + struct min_assign_base; + template<typename Left, typename Right, typename EnableIf = void> + struct max_assign_base; + template<typename Left, typename Right, typename EnableIf = void> + struct fdiv_base; + template<typename Arg, typename EnableIf = void> + struct as_min_base; + template<typename Arg, typename EnableIf = void> + struct as_max_base; + template<typename Arg, typename EnableIf = void> + struct as_zero_base; + template<typename Arg, typename EnableIf = void> + struct as_one_base; + + template<typename To, typename From, typename ToTag = typename tag<To>::type, typename FromTag = typename tag<From>::type> + struct promote; + template<typename Left, typename Right, typename LeftTag = typename tag<Left>::type, typename RightTag = typename tag<Right>::type> + struct min_assign; + template<typename Left, typename Right, typename LeftTag = typename tag<Left>::type, typename RightTag = typename tag<Right>::type> + struct max_assign; + template<typename Left, typename Right, typename LeftTag = typename tag<Left>::type, typename RightTag = typename tag<Right>::type> + struct fdiv; + template<typename Arg, typename Tag = typename tag<Arg>::type> + struct as_min; + template<typename Arg, typename Tag = typename tag<Arg>::type> + struct as_max; + template<typename Arg, typename Tag = typename tag<Arg>::type> + struct as_zero; + template<typename Arg, typename Tag = typename tag<Arg>::type> + struct as_one; + } + + namespace op + { + template<typename To> + struct promote; + struct min_assign; + struct max_assign; + struct fdiv; + struct as_min; + struct as_max; + struct as_zero; + struct as_one; + } + + namespace + { + extern op::min_assign const &min_assign; + extern op::max_assign const &max_assign; + extern op::fdiv const &fdiv; + extern op::as_min const &as_min; + extern op::as_max const &as_max; + extern op::as_zero const &as_zero; + extern op::as_one const &as_one; + } + + template<typename To, typename From> + typename lazy_disable_if<is_const<From>, mpl::if_<is_same<To, From>, To &, To> >::type + promote(From &from); + + template<typename To, typename From> + typename mpl::if_<is_same<To const, From const>, To const &, To const>::type + promote(From const &from); + + template<typename T> + struct default_; + + template<typename T> + struct one; + + template<typename T> + struct zero; + + template<typename T> + struct one_or_default; + + template<typename T> + struct zero_or_default; + +}} // namespace boost::numeric + +#endif
diff --git a/boost/boost/accumulators/statistics.hpp b/boost/boost/accumulators/statistics.hpp new file mode 100644 index 0000000..0178607 --- /dev/null +++ b/boost/boost/accumulators/statistics.hpp
@@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file statistics.hpp +/// Includes all of the Statistical Accumulators Library +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_HPP_EAN_01_17_2006 +#define BOOST_ACCUMULATORS_STATISTICS_HPP_EAN_01_17_2006 + +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/covariance.hpp> +#include <boost/accumulators/statistics/density.hpp> +#include <boost/accumulators/statistics/error_of.hpp> +#include <boost/accumulators/statistics/error_of_mean.hpp> +#include <boost/accumulators/statistics/extended_p_square.hpp> +#include <boost/accumulators/statistics/extended_p_square_quantile.hpp> +#include <boost/accumulators/statistics/kurtosis.hpp> +#include <boost/accumulators/statistics/max.hpp> +#include <boost/accumulators/statistics/mean.hpp> +#include <boost/accumulators/statistics/median.hpp> +#include <boost/accumulators/statistics/min.hpp> +#include <boost/accumulators/statistics/moment.hpp> +#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_cumul_dist.hpp> +#include <boost/accumulators/statistics/p_square_quantile.hpp> +#include <boost/accumulators/statistics/skewness.hpp> +#include <boost/accumulators/statistics/stats.hpp> +#include <boost/accumulators/statistics/sum.hpp> +#include <boost/accumulators/statistics/sum_kahan.hpp> +#include <boost/accumulators/statistics/tail.hpp> +#include <boost/accumulators/statistics/tail_quantile.hpp> +#include <boost/accumulators/statistics/tail_mean.hpp> +#include <boost/accumulators/statistics/tail_variate.hpp> +#include <boost/accumulators/statistics/tail_variate_means.hpp> +#include <boost/accumulators/statistics/variance.hpp> +#include <boost/accumulators/statistics/weighted_covariance.hpp> +#include <boost/accumulators/statistics/weighted_density.hpp> +#include <boost/accumulators/statistics/weighted_kurtosis.hpp> +#include <boost/accumulators/statistics/weighted_extended_p_square.hpp> +#include <boost/accumulators/statistics/weighted_mean.hpp> +#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_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> +#include <boost/accumulators/statistics/weighted_sum_kahan.hpp> +#include <boost/accumulators/statistics/weighted_tail_quantile.hpp> +#include <boost/accumulators/statistics/weighted_tail_mean.hpp> +#include <boost/accumulators/statistics/weighted_tail_variate_means.hpp> +#include <boost/accumulators/statistics/weighted_variance.hpp> +#include <boost/accumulators/statistics/with_error.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> +#include <boost/accumulators/statistics/variates/covariate.hpp> + +#endif
diff --git a/boost/boost/accumulators/statistics/count.hpp b/boost/boost/accumulators/statistics/count.hpp new file mode 100644 index 0000000..6d30b41 --- /dev/null +++ b/boost/boost/accumulators/statistics/count.hpp
@@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////// +// count.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_COUNT_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_COUNT_HPP_EAN_28_10_2005 + +#include <boost/mpl/always.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + /////////////////////////////////////////////////////////////////////////////// + // count_impl + struct count_impl + : accumulator_base + { + // for boost::result_of + typedef std::size_t result_type; + + count_impl(dont_care) + : cnt(0) + { + } + + void operator ()(dont_care) + { + ++this->cnt; + } + + result_type result(dont_care) const + { + return this->cnt; + } + + private: + std::size_t cnt; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::count +// +namespace tag +{ + struct count + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef mpl::always<accumulators::impl::count_impl> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::count +// +namespace extract +{ + extractor<tag::count> const count = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(count) +} + +using extract::count; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/covariance.hpp b/boost/boost/accumulators/statistics/covariance.hpp new file mode 100644 index 0000000..73c92ae --- /dev/null +++ b/boost/boost/accumulators/statistics/covariance.hpp
@@ -0,0 +1,220 @@ +/////////////////////////////////////////////////////////////////////////////// +// covariance.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_COVARIANCE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_COVARIANCE_HPP_DE_01_01_2006 + +#include <vector> +#include <limits> +#include <numeric> +#include <functional> +#include <complex> +#include <boost/mpl/assert.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/range.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/numeric/ublas/io.hpp> +#include <boost/numeric/ublas/matrix.hpp> +#include <boost/type_traits/is_scalar.hpp> +#include <boost/type_traits/is_same.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/mean.hpp> + +namespace boost { namespace numeric +{ + namespace functional + { + struct std_vector_tag; + + /////////////////////////////////////////////////////////////////////////////// + // functional::outer_product + template<typename Left, typename Right, typename EnableIf = void> + struct outer_product_base + : functional::multiplies<Left, Right> + {}; + + template<typename Left, typename Right, typename LeftTag = typename tag<Left>::type, typename RightTag = typename tag<Right>::type> + struct outer_product + : outer_product_base<Left, Right, void> + {}; + + template<typename Left, typename Right> + struct outer_product<Left, Right, std_vector_tag, std_vector_tag> + : std::binary_function< + Left + , Right + , ublas::matrix< + typename functional::multiplies< + typename Left::value_type + , typename Right::value_type + >::result_type + > + > + { + typedef + ublas::matrix< + typename functional::multiplies< + typename Left::value_type + , typename Right::value_type + >::result_type + > + result_type; + + result_type + operator ()(Left & left, Right & right) const + { + std::size_t left_size = left.size(); + std::size_t right_size = right.size(); + result_type result(left_size, right_size); + for (std::size_t i = 0; i < left_size; ++i) + for (std::size_t j = 0; j < right_size; ++j) + result(i,j) = numeric::multiplies(left[i], right[j]); + return result; + } + }; + } + + namespace op + { + struct outer_product + : boost::detail::function2<functional::outer_product<_1, _2, functional::tag<_1>, functional::tag<_2> > > + {}; + } + + namespace + { + op::outer_product const &outer_product = boost::detail::pod_singleton<op::outer_product>::instance; + } + +}} + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // covariance_impl + // + /** + @brief Covariance Estimator + + An iterative Monte Carlo estimator for the covariance \f$\mathrm{Cov}(X,X')\f$, where \f$X\f$ is a sample + and \f$X'\f$ is a variate, is given by: + + \f[ + \hat{c}_n = \frac{n-1}{n} \hat{c}_{n-1} + \frac{1}{n-1}(X_n - \hat{\mu}_n)(X_n' - \hat{\mu}_n'),\quad n\ge2,\quad\hat{c}_1 = 0, + \f] + + \f$\hat{\mu}_n\f$ and \f$\hat{\mu}_n'\f$ being the means of the samples and variates. + */ + template<typename Sample, typename VariateType, typename VariateTag> + struct covariance_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type sample_type; + typedef typename numeric::functional::fdiv<VariateType, std::size_t>::result_type variate_type; + // for boost::result_of + typedef typename numeric::functional::outer_product<sample_type, variate_type>::result_type result_type; + + template<typename Args> + covariance_impl(Args const &args) + : cov_( + numeric::outer_product( + numeric::fdiv(args[sample | Sample()], (std::size_t)1) + , numeric::fdiv(args[parameter::keyword<VariateTag>::get() | VariateType()], (std::size_t)1) + ) + ) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + if (cnt > 1) + { + extractor<tag::mean_of_variates<VariateType, VariateTag> > const some_mean_of_variates = {}; + + this->cov_ = this->cov_*(cnt-1.)/cnt + + numeric::outer_product( + some_mean_of_variates(args) - args[parameter::keyword<VariateTag>::get()] + , mean(args) - args[sample] + ) / (cnt-1.); + } + } + + result_type result(dont_care) const + { + return this->cov_; + } + + private: + result_type cov_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::covariance +// +namespace tag +{ + template<typename VariateType, typename VariateTag> + struct covariance + : depends_on<count, mean, mean_of_variates<VariateType, VariateTag> > + { + typedef accumulators::impl::covariance_impl<mpl::_1, VariateType, VariateTag> impl; + }; + + struct abstract_covariance + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::covariance +// +namespace extract +{ + extractor<tag::abstract_covariance> const covariance = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(covariance) +} + +using extract::covariance; + +template<typename VariateType, typename VariateTag> +struct feature_of<tag::covariance<VariateType, VariateTag> > + : feature_of<tag::abstract_covariance> +{ +}; + +// So that covariance can be automatically substituted with +// weighted_covariance when the weight parameter is non-void. +template<typename VariateType, typename VariateTag> +struct as_weighted_feature<tag::covariance<VariateType, VariateTag> > +{ + typedef tag::weighted_covariance<VariateType, VariateTag> type; +}; + +template<typename VariateType, typename VariateTag> +struct feature_of<tag::weighted_covariance<VariateType, VariateTag> > + : feature_of<tag::covariance<VariateType, VariateTag> > +{}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/density.hpp b/boost/boost/accumulators/statistics/density.hpp new file mode 100644 index 0000000..88ca17d --- /dev/null +++ b/boost/boost/accumulators/statistics/density.hpp
@@ -0,0 +1,250 @@ + +/////////////////////////////////////////////////////////////////////////////// +// density.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_DENSITY_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_DENSITY_HPP_DE_01_01_2006 + +#include <vector> +#include <limits> +#include <functional> +#include <boost/range.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/accumulators_fwd.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/max.hpp> +#include <boost/accumulators/statistics/min.hpp> + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// cache_size and num_bins named parameters +// +BOOST_PARAMETER_NESTED_KEYWORD(tag, density_cache_size, cache_size) +BOOST_PARAMETER_NESTED_KEYWORD(tag, density_num_bins, num_bins) + +BOOST_ACCUMULATORS_IGNORE_GLOBAL(density_cache_size) +BOOST_ACCUMULATORS_IGNORE_GLOBAL(density_num_bins) + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // density_impl + // density histogram + /** + @brief Histogram density estimator + + The histogram density estimator returns a histogram of the sample distribution. The positions and sizes of the bins + are determined using a specifiable number of cached samples (cache_size). The range between the minimum and the + maximum of the cached samples is subdivided into a specifiable number of bins (num_bins) of same size. Additionally, + an under- and an overflow bin is added to capture future under- and overflow samples. Once the bins are determined, + the cached samples and all subsequent samples are added to the correct bins. At the end, a range of std::pair is + return, where each pair contains the position of the bin (lower bound) and the samples count (normalized with the + total number of samples). + + @param density_cache_size Number of first samples used to determine min and max. + @param density_num_bins Number of bins (two additional bins collect under- and overflow samples). + */ + template<typename Sample> + struct density_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<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> + density_impl(Args const &args) + : cache_size(args[density_cache_size]) + , cache(cache_size) + , num_bins(args[density_num_bins]) + , samples_in_bin(num_bins + 2, 0.) + , bin_positions(num_bins + 2) + , histogram( + num_bins + 2 + , std::make_pair( + numeric::fdiv(args[sample | Sample()],(std::size_t)1) + , numeric::fdiv(args[sample | Sample()],(std::size_t)1) + ) + ) + , is_dirty(true) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + this->is_dirty = true; + + std::size_t cnt = count(args); + + // Fill up cache with cache_size first samples + if (cnt <= this->cache_size) + { + this->cache[cnt - 1] = args[sample]; + } + + // Once cache_size samples have been accumulated, create num_bins bins of same size between + // the minimum and maximum of the cached samples as well as 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) + { + float_type minimum = numeric::fdiv((min)(args), (std::size_t)1); + float_type maximum = numeric::fdiv((max)(args), (std::size_t)1); + float_type bin_size = numeric::fdiv(maximum - minimum, this->num_bins ); + + // determine bin positions (their lower bounds) + for (std::size_t i = 0; i < this->num_bins + 2; ++i) + { + this->bin_positions[i] = minimum + (i - 1.) * bin_size; + } + + for (typename array_type::const_iterator iter = this->cache.begin(); iter != this->cache.end(); ++iter) + { + if (*iter < this->bin_positions[1]) + { + ++(this->samples_in_bin[0]); + } + else if (*iter >= this->bin_positions[this->num_bins + 1]) + { + ++(this->samples_in_bin[this->num_bins + 1]); + } + else + { + typename array_type::iterator it = std::upper_bound( + this->bin_positions.begin() + , this->bin_positions.end() + , *iter + ); + + std::size_t d = std::distance(this->bin_positions.begin(), it); + ++(this->samples_in_bin[d - 1]); + } + } + } + // Add each subsequent sample to the correct bin + else if (cnt > this->cache_size) + { + if (args[sample] < this->bin_positions[1]) + { + ++(this->samples_in_bin[0]); + } + else if (args[sample] >= this->bin_positions[this->num_bins + 1]) + { + ++(this->samples_in_bin[this->num_bins + 1]); + } + else + { + typename array_type::iterator it = std::upper_bound( + this->bin_positions.begin() + , this->bin_positions.end() + , args[sample] + ); + + std::size_t d = std::distance(this->bin_positions.begin(), it); + ++(this->samples_in_bin[d - 1]); + } + } + } + + /** + @pre The number of samples must meet or exceed the cache size + */ + 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 bin_positions[i] (x-axis of histogram) and + // samples_in_bin[i] / cnt (y-axis of histogram). + + for (std::size_t i = 0; i < this->num_bins + 2; ++i) + { + this->histogram[i] = std::make_pair(this->bin_positions[i], numeric::fdiv(this->samples_in_bin[i], count(args))); + } + } + // returns a range of pairs + return make_iterator_range(this->histogram); + } + + private: + std::size_t cache_size; // number of cached samples + array_type cache; // cache to store the first cache_size samples + std::size_t num_bins; // number of bins + array_type samples_in_bin; // number of samples in each bin + array_type bin_positions; // lower bounds of bins + mutable histogram_type histogram; // histogram + mutable bool is_dirty; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::density +// +namespace tag +{ + struct density + : depends_on<count, min, max> + , density_cache_size + , density_num_bins + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::density_impl<mpl::_1> impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::density::cache_size named parameter + /// tag::density::num_bins named parameter + static boost::parameter::keyword<density_cache_size> const cache_size; + static boost::parameter::keyword<density_num_bins> const num_bins; + #endif + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::density +// +namespace extract +{ + extractor<tag::density> const density = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(density) +} + +using extract::density; + +// So that density can be automatically substituted +// with weighted_density when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::density> +{ + typedef tag::weighted_density type; +}; + +template<> +struct feature_of<tag::weighted_density> + : feature_of<tag::density> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/error_of.hpp b/boost/boost/accumulators/statistics/error_of.hpp new file mode 100644 index 0000000..a29da02 --- /dev/null +++ b/boost/boost/accumulators/statistics/error_of.hpp
@@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////// +// error_of.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_ERROR_OF_HPP_EAN_29_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_ERROR_OF_HPP_EAN_29_11_2005 + +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /// INTERNAL ONLY + /// + template<typename Feature> + struct this_feature_has_no_error_calculation + : mpl::false_ + { + }; + + /////////////////////////////////////////////////////////////////////////////// + // error_of_impl + /// INTERNAL ONLY + /// + template<typename Sample, typename Feature> + struct error_of_impl + : accumulator_base + { + // TODO: specialize this on the specific features that have errors we're + // interested in. + BOOST_MPL_ASSERT((this_feature_has_no_error_calculation<Feature>)); + + // for boost::result_of + typedef int result_type; + + error_of_impl(dont_care) + { + } + + result_type result(dont_care) const + { + return 0; + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::error_of +// +namespace tag +{ + template<typename Feature> + struct error_of + : depends_on<Feature> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::error_of_impl<mpl::_1, Feature> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::error_of +// +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, error_of, (typename)) +} + +using extract::error_of; + +// make tag::error_of<tag::feature(modifier)> work +template<typename Feature> +struct as_feature<tag::error_of<Feature> > +{ + typedef tag::error_of<typename as_feature<Feature>::type> type; +}; + +// make error_of<tag::mean> work with non-void weights (should become +// error_of<tag::weighted_mean> +template<typename Feature> +struct as_weighted_feature<tag::error_of<Feature> > +{ + typedef tag::error_of<typename as_weighted_feature<Feature>::type> type; +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/error_of_mean.hpp b/boost/boost/accumulators/statistics/error_of_mean.hpp new file mode 100644 index 0000000..7cd923d --- /dev/null +++ b/boost/boost/accumulators/statistics/error_of_mean.hpp
@@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////// +// error_of.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_ERROR_OF_MEAN_HPP_EAN_27_03_2006 +#define BOOST_ACCUMULATORS_STATISTICS_ERROR_OF_MEAN_HPP_EAN_27_03_2006 + +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/error_of.hpp> +#include <boost/accumulators/statistics/variance.hpp> +#include <boost/accumulators/statistics/count.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // error_of_mean_impl + template<typename Sample, typename Variance> + struct error_of_mean_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + error_of_mean_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + using namespace std; + extractor<Variance> const variance = {}; + return sqrt(numeric::fdiv(variance(args), count(args) - 1)); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::error_of +// +namespace tag +{ + template<> + struct error_of<mean> + : depends_on<lazy_variance, count> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::error_of_mean_impl<mpl::_1, lazy_variance> impl; + }; + + template<> + struct error_of<immediate_mean> + : depends_on<variance, count> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::error_of_mean_impl<mpl::_1, variance> impl; + }; +} + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/extended_p_square.hpp b/boost/boost/accumulators/statistics/extended_p_square.hpp new file mode 100644 index 0000000..e6cc8dc --- /dev/null +++ b/boost/boost/accumulators/statistics/extended_p_square.hpp
@@ -0,0 +1,295 @@ +/////////////////////////////////////////////////////////////////////////////// +// extended_p_square.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_EXTENDED_SINGLE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_EXTENDED_SINGLE_HPP_DE_01_01_2006 + +#include <vector> +#include <functional> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/iterator/transform_iterator.hpp> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/iterator/permutation_iterator.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/times2_iterator.hpp> + +namespace boost { namespace accumulators +{ +/////////////////////////////////////////////////////////////////////////////// +// probabilities named parameter +// +BOOST_PARAMETER_NESTED_KEYWORD(tag, extended_p_square_probabilities, probabilities) + +BOOST_ACCUMULATORS_IGNORE_GLOBAL(extended_p_square_probabilities) + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // extended_p_square_impl + // multiple quantile estimation + /** + @brief Multiple quantile estimation with the extended \f$P^2\f$ algorithm + + Extended \f$P^2\f$ algorithm for estimation of several quantiles without storing samples. + Assume that \f$m\f$ quantiles \f$\xi_{p_1}, \ldots, \xi_{p_m}\f$ are to be estimated. + Instead of storing the whole sample cumulative distribution, the algorithm maintains only + \f$m+2\f$ principal markers and \f$m+1\f$ middle markers, whose positions are updated + with each sample and whose heights are adjusted (if necessary) using a piecewise-parablic + formula. The heights of these central markers are the current estimates of the quantiles + and returned as an iterator range. + + For further details, see + + K. E. E. Raatikainen, Simultaneous estimation of several quantiles, Simulation, Volume 49, + Number 4 (October), 1986, p. 159-164. + + The extended \f$ P^2 \f$ algorithm generalizes the \f$ P^2 \f$ algorithm of + + R. Jain and I. Chlamtac, The P^2 algorithm for dynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param extended_p_square_probabilities A vector of quantile probabilities. + */ + template<typename Sample> + struct extended_p_square_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + typedef std::vector<float_type> array_type; + // for boost::result_of + typedef iterator_range< + detail::lvalue_index_iterator< + permutation_iterator< + typename array_type::const_iterator + , detail::times2_iterator + > + > + > result_type; + + template<typename Args> + extended_p_square_impl(Args const &args) + : probabilities( + boost::begin(args[extended_p_square_probabilities]) + , boost::end(args[extended_p_square_probabilities]) + ) + , heights(2 * probabilities.size() + 3) + , actual_positions(heights.size()) + , desired_positions(heights.size()) + , positions_increments(heights.size()) + { + std::size_t num_quantiles = this->probabilities.size(); + std::size_t num_markers = this->heights.size(); + + for(std::size_t i = 0; i < num_markers; ++i) + { + this->actual_positions[i] = i + 1; + } + + this->positions_increments[0] = 0.; + this->positions_increments[num_markers - 1] = 1.; + + for(std::size_t i = 0; i < num_quantiles; ++i) + { + this->positions_increments[2 * i + 2] = probabilities[i]; + } + + for(std::size_t i = 0; i <= num_quantiles; ++i) + { + this->positions_increments[2 * i + 1] = + 0.5 * (this->positions_increments[2 * i] + this->positions_increments[2 * i + 2]); + } + + for(std::size_t i = 0; i < num_markers; ++i) + { + this->desired_positions[i] = 1. + 2. * (num_quantiles + 1.) * this->positions_increments[i]; + } + } + + template<typename Args> + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + // m+2 principal markers and m+1 middle markers + std::size_t num_markers = 2 * this->probabilities.size() + 3; + + // first accumulate num_markers samples + if(cnt <= num_markers) + { + this->heights[cnt - 1] = args[sample]; + + // complete the initialization of heights by sorting + if(cnt == num_markers) + { + std::sort(this->heights.begin(), this->heights.end()); + } + } + else + { + std::size_t sample_cell = 1; + + // find cell k = sample_cell such that heights[k-1] <= sample < heights[k] + if(args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + sample_cell = 1; + } + else if(args[sample] >= this->heights[num_markers - 1]) + { + this->heights[num_markers - 1] = args[sample]; + sample_cell = num_markers - 1; + } + else + { + typedef typename array_type::iterator iterator; + iterator it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // update actual positions of all markers above sample_cell index + for(std::size_t i = sample_cell; i < num_markers; ++i) + { + ++this->actual_positions[i]; + } + + // update desired positions of all markers + for(std::size_t i = 0; i < num_markers; ++i) + { + this->desired_positions[i] += this->positions_increments[i]; + } + + // adjust heights and actual positions of markers 1 to num_markers-2 if necessary + for(std::size_t i = 1; i <= num_markers - 2; ++i) + { + // offset to desired position + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i+1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i-1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i+1] - this->heights[i]) / dp; + float_type hm = (this->heights[i-1] - this->heights[i]) / dm; + + if((d >= 1 && dp > 1) || (d <= -1 && dm < -1)) + { + short sign_d = static_cast<short>(d / std::abs(d)); + + float_type h = this->heights[i] + sign_d / (dp - dm) * ((sign_d - dm)*hp + + (dp - sign_d) * hm); + + // try adjusting heights[i] using p-squared formula + if(this->heights[i - 1] < h && h < this->heights[i + 1]) + { + this->heights[i] = h; + } + else + { + // use linear formula + if(d > 0) + { + this->heights[i] += hp; + } + if(d < 0) + { + this->heights[i] -= hm; + } + } + this->actual_positions[i] += sign_d; + } + } + } + } + + result_type result(dont_care) const + { + // for i in [1,probabilities.size()], return heights[i * 2] + detail::times2_iterator idx_begin = detail::make_times2_iterator(1); + detail::times2_iterator idx_end = detail::make_times2_iterator(this->probabilities.size() + 1); + + return result_type( + make_permutation_iterator(this->heights.begin(), idx_begin) + , make_permutation_iterator(this->heights.begin(), idx_end) + ); + } + + private: + array_type probabilities; // the quantile probabilities + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // d_i + array_type positions_increments; // f_i + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::extended_p_square +// +namespace tag +{ + struct extended_p_square + : depends_on<count> + , extended_p_square_probabilities + { + typedef accumulators::impl::extended_p_square_impl<mpl::_1> impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::extended_p_square::probabilities named parameter + static boost::parameter::keyword<tag::probabilities> const probabilities; + #endif + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::extended_p_square +// +namespace extract +{ + extractor<tag::extended_p_square> const extended_p_square = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(extended_p_square) +} + +using extract::extended_p_square; + +// So that extended_p_square can be automatically substituted with +// weighted_extended_p_square when the weight parameter is non-void +template<> +struct as_weighted_feature<tag::extended_p_square> +{ + typedef tag::weighted_extended_p_square type; +}; + +template<> +struct feature_of<tag::weighted_extended_p_square> + : feature_of<tag::extended_p_square> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/extended_p_square_quantile.hpp b/boost/boost/accumulators/statistics/extended_p_square_quantile.hpp new file mode 100644 index 0000000..a17843d --- /dev/null +++ b/boost/boost/accumulators/statistics/extended_p_square_quantile.hpp
@@ -0,0 +1,320 @@ +/////////////////////////////////////////////////////////////////////////////// +// extended_p_square_quantile.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_EXTENDED_SINGLE_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_EXTENDED_SINGLE_QUANTILE_HPP_DE_01_01_2006 + +#include <vector> +#include <functional> +#include <boost/throw_exception.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/iterator/transform_iterator.hpp> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/iterator/permutation_iterator.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/type_traits/is_same.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> +#include <boost/accumulators/statistics/extended_p_square.hpp> +#include <boost/accumulators/statistics/weighted_extended_p_square.hpp> +#include <boost/accumulators/statistics/times2_iterator.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // extended_p_square_quantile_impl + // single quantile estimation + /** + @brief Quantile estimation using the extended \f$P^2\f$ algorithm for weighted and unweighted samples + + Uses the quantile estimates calculated by the extended \f$P^2\f$ algorithm to compute + intermediate quantile estimates by means of quadratic interpolation. + + @param quantile_probability The probability of the quantile to be estimated. + */ + template<typename Sample, typename Impl1, typename Impl2> // Impl1: weighted/unweighted // Impl2: linear/quadratic + struct extended_p_square_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + typedef std::vector<float_type> array_type; + typedef iterator_range< + detail::lvalue_index_iterator< + permutation_iterator< + typename array_type::const_iterator + , detail::times2_iterator + > + > + > range_type; + // for boost::result_of + typedef float_type result_type; + + template<typename Args> + extended_p_square_quantile_impl(Args const &args) + : probabilities( + boost::begin(args[extended_p_square_probabilities]) + , boost::end(args[extended_p_square_probabilities]) + ) + { + } + + template<typename Args> + result_type result(Args const &args) const + { + typedef + typename mpl::if_< + is_same<Impl1, weighted> + , tag::weighted_extended_p_square + , tag::extended_p_square + >::type + extended_p_square_tag; + + extractor<extended_p_square_tag> const some_extended_p_square = {}; + + array_type heights(some_extended_p_square(args).size()); + std::copy(some_extended_p_square(args).begin(), some_extended_p_square(args).end(), heights.begin()); + + this->probability = args[quantile_probability]; + + typename array_type::const_iterator iter_probs = std::lower_bound(this->probabilities.begin(), this->probabilities.end(), this->probability); + std::size_t dist = std::distance(this->probabilities.begin(), iter_probs); + typename array_type::const_iterator iter_heights = heights.begin() + dist; + + // If this->probability is not in a valid range return NaN or throw exception + if (this->probability < *this->probabilities.begin() || this->probability > *(this->probabilities.end() - 1)) + { + if (std::numeric_limits<result_type>::has_quiet_NaN) + { + return std::numeric_limits<result_type>::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "probability = " << this->probability << " is not in valid range ("; + msg << *this->probabilities.begin() << ", " << *(this->probabilities.end() - 1) << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return Sample(0); + } + + } + + if (*iter_probs == this->probability) + { + return heights[dist]; + } + else + { + result_type res; + + if (is_same<Impl2, linear>::value) + { + ///////////////////////////////////////////////////////////////////////////////// + // LINEAR INTERPOLATION + // + float_type p1 = *iter_probs; + float_type p0 = *(iter_probs - 1); + float_type h1 = *iter_heights; + float_type h0 = *(iter_heights - 1); + + float_type a = numeric::fdiv(h1 - h0, p1 - p0); + float_type b = h1 - p1 * a; + + res = a * this->probability + b; + } + else + { + ///////////////////////////////////////////////////////////////////////////////// + // QUADRATIC INTERPOLATION + // + float_type p0, p1, p2; + float_type h0, h1, h2; + + if ( (dist == 1 || *iter_probs - this->probability <= this->probability - *(iter_probs - 1) ) && dist != this->probabilities.size() - 1 ) + { + p0 = *(iter_probs - 1); + p1 = *iter_probs; + p2 = *(iter_probs + 1); + h0 = *(iter_heights - 1); + h1 = *iter_heights; + h2 = *(iter_heights + 1); + } + else + { + p0 = *(iter_probs - 2); + p1 = *(iter_probs - 1); + p2 = *iter_probs; + h0 = *(iter_heights - 2); + h1 = *(iter_heights - 1); + h2 = *iter_heights; + } + + float_type hp21 = numeric::fdiv(h2 - h1, p2 - p1); + float_type hp10 = numeric::fdiv(h1 - h0, p1 - p0); + float_type p21 = numeric::fdiv(p2 * p2 - p1 * p1, p2 - p1); + float_type p10 = numeric::fdiv(p1 * p1 - p0 * p0, p1 - p0); + + float_type a = numeric::fdiv(hp21 - hp10, p21 - p10); + float_type b = hp21 - a * p21; + float_type c = h2 - a * p2 * p2 - b * p2; + + res = a * this->probability * this-> probability + b * this->probability + c; + } + + return res; + } + + } + private: + + array_type probabilities; + mutable float_type probability; + + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::extended_p_square_quantile +// +namespace tag +{ + struct extended_p_square_quantile + : depends_on<extended_p_square> + { + typedef accumulators::impl::extended_p_square_quantile_impl<mpl::_1, unweighted, linear> impl; + }; + struct extended_p_square_quantile_quadratic + : depends_on<extended_p_square> + { + typedef accumulators::impl::extended_p_square_quantile_impl<mpl::_1, unweighted, quadratic> impl; + }; + struct weighted_extended_p_square_quantile + : depends_on<weighted_extended_p_square> + { + typedef accumulators::impl::extended_p_square_quantile_impl<mpl::_1, weighted, linear> impl; + }; + struct weighted_extended_p_square_quantile_quadratic + : depends_on<weighted_extended_p_square> + { + typedef accumulators::impl::extended_p_square_quantile_impl<mpl::_1, weighted, quadratic> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::extended_p_square_quantile +// extract::weighted_extended_p_square_quantile +// +namespace extract +{ + extractor<tag::extended_p_square_quantile> const extended_p_square_quantile = {}; + extractor<tag::extended_p_square_quantile_quadratic> const extended_p_square_quantile_quadratic = {}; + extractor<tag::weighted_extended_p_square_quantile> const weighted_extended_p_square_quantile = {}; + extractor<tag::weighted_extended_p_square_quantile_quadratic> const weighted_extended_p_square_quantile_quadratic = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(extended_p_square_quantile) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(extended_p_square_quantile_quadratic) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_extended_p_square_quantile) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_extended_p_square_quantile_quadratic) +} + +using extract::extended_p_square_quantile; +using extract::extended_p_square_quantile_quadratic; +using extract::weighted_extended_p_square_quantile; +using extract::weighted_extended_p_square_quantile_quadratic; + +// extended_p_square_quantile(linear) -> extended_p_square_quantile +template<> +struct as_feature<tag::extended_p_square_quantile(linear)> +{ + typedef tag::extended_p_square_quantile type; +}; + +// extended_p_square_quantile(quadratic) -> extended_p_square_quantile_quadratic +template<> +struct as_feature<tag::extended_p_square_quantile(quadratic)> +{ + typedef tag::extended_p_square_quantile_quadratic type; +}; + +// weighted_extended_p_square_quantile(linear) -> weighted_extended_p_square_quantile +template<> +struct as_feature<tag::weighted_extended_p_square_quantile(linear)> +{ + typedef tag::weighted_extended_p_square_quantile type; +}; + +// weighted_extended_p_square_quantile(quadratic) -> weighted_extended_p_square_quantile_quadratic +template<> +struct as_feature<tag::weighted_extended_p_square_quantile(quadratic)> +{ + typedef tag::weighted_extended_p_square_quantile_quadratic type; +}; + +// for the purposes of feature-based dependency resolution, +// extended_p_square_quantile and weighted_extended_p_square_quantile +// provide the same feature as quantile +template<> +struct feature_of<tag::extended_p_square_quantile> + : feature_of<tag::quantile> +{ +}; +template<> +struct feature_of<tag::extended_p_square_quantile_quadratic> + : feature_of<tag::quantile> +{ +}; +// So that extended_p_square_quantile can be automatically substituted with +// weighted_extended_p_square_quantile when the weight parameter is non-void +template<> +struct as_weighted_feature<tag::extended_p_square_quantile> +{ + typedef tag::weighted_extended_p_square_quantile type; +}; + +template<> +struct feature_of<tag::weighted_extended_p_square_quantile> + : feature_of<tag::extended_p_square_quantile> +{ +}; + +// So that extended_p_square_quantile_quadratic can be automatically substituted with +// weighted_extended_p_square_quantile_quadratic when the weight parameter is non-void +template<> +struct as_weighted_feature<tag::extended_p_square_quantile_quadratic> +{ + typedef tag::weighted_extended_p_square_quantile_quadratic type; +}; +template<> +struct feature_of<tag::weighted_extended_p_square_quantile_quadratic> + : feature_of<tag::extended_p_square_quantile_quadratic> +{ +}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif
diff --git a/boost/boost/accumulators/statistics/kurtosis.hpp b/boost/boost/accumulators/statistics/kurtosis.hpp new file mode 100644 index 0000000..76c93d3 --- /dev/null +++ b/boost/boost/accumulators/statistics/kurtosis.hpp
@@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////////// +// kurtosis.hpp +// +// Copyright 2006 Olivier Gygi, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_KURTOSIS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_KURTOSIS_HPP_EAN_28_10_2005 + +#include <limits> +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics/mean.hpp> +#include <boost/accumulators/statistics/moment.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // kurtosis_impl + /** + @brief Kurtosis estimation + + The kurtosis of a sample distribution is defined as the ratio of the 4th central moment and the square of the 2nd central + moment (the variance) of the samples, minus 3. The term \f$ -3 \f$ is added in order to ensure that the normal distribution + has zero kurtosis. The kurtosis can also be expressed by the simple moments: + + \f[ + \hat{g}_2 = + \frac + {\widehat{m}_n^{(4)}-4\widehat{m}_n^{(3)}\hat{\mu}_n+6\widehat{m}_n^{(2)}\hat{\mu}_n^2-3\hat{\mu}_n^4} + {\left(\widehat{m}_n^{(2)} - \hat{\mu}_n^{2}\right)^2} - 3, + \f] + + where \f$ \widehat{m}_n^{(i)} \f$ are the \f$ i \f$-th moment and \f$ \hat{\mu}_n \f$ the mean (first moment) of the + \f$ n \f$ samples. + */ + template<typename Sample> + struct kurtosis_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, Sample>::result_type result_type; + + kurtosis_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + return numeric::fdiv( + accumulators::moment<4>(args) + - 4. * accumulators::moment<3>(args) * mean(args) + + 6. * accumulators::moment<2>(args) * mean(args) * mean(args) + - 3. * mean(args) * mean(args) * mean(args) * mean(args) + , ( accumulators::moment<2>(args) - mean(args) * mean(args) ) + * ( accumulators::moment<2>(args) - mean(args) * mean(args) ) + ) - 3.; + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::kurtosis +// +namespace tag +{ + struct kurtosis + : depends_on<mean, moment<2>, moment<3>, moment<4> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::kurtosis_impl<mpl::_1> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::kurtosis +// +namespace extract +{ + extractor<tag::kurtosis> const kurtosis = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(kurtosis) +} + +using extract::kurtosis; + +// So that kurtosis can be automatically substituted with +// weighted_kurtosis when the weight parameter is non-void +template<> +struct as_weighted_feature<tag::kurtosis> +{ + typedef tag::weighted_kurtosis type; +}; + +template<> +struct feature_of<tag::weighted_kurtosis> + : feature_of<tag::kurtosis> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/max.hpp b/boost/boost/accumulators/statistics/max.hpp new file mode 100644 index 0000000..820f659 --- /dev/null +++ b/boost/boost/accumulators/statistics/max.hpp
@@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////////// +// max.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MAX_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MAX_HPP_EAN_28_10_2005 + +#include <limits> +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // max_impl + template<typename Sample> + struct max_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + template<typename Args> + max_impl(Args const &args) + : max_(numeric::as_min(args[sample | Sample()])) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + numeric::max_assign(this->max_, args[sample]); + } + + result_type result(dont_care) const + { + return this->max_; + } + + private: + Sample max_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::max +// +namespace tag +{ + struct max + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::max_impl<mpl::_1> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::max +// +namespace extract +{ + extractor<tag::max> const max = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(max) +} + +using extract::max; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/mean.hpp b/boost/boost/accumulators/statistics/mean.hpp new file mode 100644 index 0000000..4788837 --- /dev/null +++ b/boost/boost/accumulators/statistics/mean.hpp
@@ -0,0 +1,298 @@ +/////////////////////////////////////////////////////////////////////////////// +// mean.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MEAN_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MEAN_HPP_EAN_28_10_2005 + +#include <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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/sum.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // mean_impl + // lazy, by default + template<typename Sample, typename SumFeature> + struct mean_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + mean_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + extractor<SumFeature> sum; + return numeric::fdiv(sum(args), count(args)); + } + }; + + template<typename Sample, typename Tag> + struct immediate_mean_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + template<typename Args> + immediate_mean_impl(Args const &args) + : mean(numeric::fdiv(args[sample | Sample()], numeric::one<std::size_t>::value)) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + this->mean = numeric::fdiv( + (this->mean * (cnt - 1)) + args[parameter::keyword<Tag>::get()] + , cnt + ); + } + + result_type result(dont_care) const + { + return this->mean; + } + + private: + result_type mean; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::mean +// tag::immediate_mean +// tag::mean_of_weights +// tag::immediate_mean_of_weights +// tag::mean_of_variates +// tag::immediate_mean_of_variates +// +namespace tag +{ + struct mean + : depends_on<count, sum> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::mean_impl<mpl::_1, sum> impl; + }; + struct immediate_mean + : depends_on<count> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_mean_impl<mpl::_1, tag::sample> impl; + }; + struct mean_of_weights + : depends_on<count, sum_of_weights> + { + typedef mpl::true_ is_weight_accumulator; + /// INTERNAL ONLY + /// + typedef accumulators::impl::mean_impl<mpl::_2, sum_of_weights> impl; + }; + struct immediate_mean_of_weights + : depends_on<count> + { + typedef mpl::true_ is_weight_accumulator; + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_mean_impl<mpl::_2, tag::weight> impl; + }; + template<typename VariateType, typename VariateTag> + struct mean_of_variates + : depends_on<count, sum_of_variates<VariateType, VariateTag> > + { + /// INTERNAL ONLY + /// + typedef mpl::always<accumulators::impl::mean_impl<VariateType, sum_of_variates<VariateType, VariateTag> > > impl; + }; + template<typename VariateType, typename VariateTag> + struct immediate_mean_of_variates + : depends_on<count> + { + /// INTERNAL ONLY + /// + typedef mpl::always<accumulators::impl::immediate_mean_impl<VariateType, VariateTag> > impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::mean +// extract::mean_of_weights +// extract::mean_of_variates +// +namespace extract +{ + extractor<tag::mean> const mean = {}; + extractor<tag::mean_of_weights> const mean_of_weights = {}; + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, mean_of_variates, (typename)(typename)) + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(mean) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(mean_of_weights) +} + +using extract::mean; +using extract::mean_of_weights; +using extract::mean_of_variates; + +// mean(lazy) -> mean +template<> +struct as_feature<tag::mean(lazy)> +{ + typedef tag::mean type; +}; + +// mean(immediate) -> immediate_mean +template<> +struct as_feature<tag::mean(immediate)> +{ + typedef tag::immediate_mean type; +}; + +// mean_of_weights(lazy) -> mean_of_weights +template<> +struct as_feature<tag::mean_of_weights(lazy)> +{ + typedef tag::mean_of_weights type; +}; + +// mean_of_weights(immediate) -> immediate_mean_of_weights +template<> +struct as_feature<tag::mean_of_weights(immediate)> +{ + typedef tag::immediate_mean_of_weights type; +}; + +// mean_of_variates<VariateType, VariateTag>(lazy) -> mean_of_variates<VariateType, VariateTag> +template<typename VariateType, typename VariateTag> +struct as_feature<tag::mean_of_variates<VariateType, VariateTag>(lazy)> +{ + typedef tag::mean_of_variates<VariateType, VariateTag> type; +}; + +// mean_of_variates<VariateType, VariateTag>(immediate) -> immediate_mean_of_variates<VariateType, VariateTag> +template<typename VariateType, typename VariateTag> +struct as_feature<tag::mean_of_variates<VariateType, VariateTag>(immediate)> +{ + typedef tag::immediate_mean_of_variates<VariateType, VariateTag> type; +}; + +// for the purposes of feature-based dependency resolution, +// immediate_mean provides the same feature as mean +template<> +struct feature_of<tag::immediate_mean> + : feature_of<tag::mean> +{ +}; + +// for the purposes of feature-based dependency resolution, +// immediate_mean provides the same feature as mean +template<> +struct feature_of<tag::immediate_mean_of_weights> + : feature_of<tag::mean_of_weights> +{ +}; + +// for the purposes of feature-based dependency resolution, +// immediate_mean provides the same feature as mean +template<typename VariateType, typename VariateTag> +struct feature_of<tag::immediate_mean_of_variates<VariateType, VariateTag> > + : feature_of<tag::mean_of_variates<VariateType, VariateTag> > +{ +}; + +// So that mean can be automatically substituted with +// weighted_mean when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::mean> +{ + typedef tag::weighted_mean type; +}; + +template<> +struct feature_of<tag::weighted_mean> + : feature_of<tag::mean> +{}; + +// So that immediate_mean can be automatically substituted with +// immediate_weighted_mean when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::immediate_mean> +{ + typedef tag::immediate_weighted_mean type; +}; + +template<> +struct feature_of<tag::immediate_weighted_mean> + : feature_of<tag::immediate_mean> +{}; + +// So that mean_of_weights<> can be automatically substituted with +// weighted_mean_of_variates<> when the weight parameter is non-void. +template<typename VariateType, typename VariateTag> +struct as_weighted_feature<tag::mean_of_variates<VariateType, VariateTag> > +{ + typedef tag::weighted_mean_of_variates<VariateType, VariateTag> type; +}; + +template<typename VariateType, typename VariateTag> +struct feature_of<tag::weighted_mean_of_variates<VariateType, VariateTag> > + : feature_of<tag::mean_of_variates<VariateType, VariateTag> > +{ +}; + +// So that immediate_mean_of_weights<> can be automatically substituted with +// immediate_weighted_mean_of_variates<> when the weight parameter is non-void. +template<typename VariateType, typename VariateTag> +struct as_weighted_feature<tag::immediate_mean_of_variates<VariateType, VariateTag> > +{ + typedef tag::immediate_weighted_mean_of_variates<VariateType, VariateTag> type; +}; + +template<typename VariateType, typename VariateTag> +struct feature_of<tag::immediate_weighted_mean_of_variates<VariateType, VariateTag> > + : feature_of<tag::immediate_mean_of_variates<VariateType, VariateTag> > +{ +}; + +//////////////////////////////////////////////////////////////////////////// +//// droppable_accumulator<mean_impl> +//// need to specialize droppable lazy mean to cache the result at the +//// point the accumulator is dropped. +///// INTERNAL ONLY +///// +//template<typename Sample, typename SumFeature> +//struct droppable_accumulator<impl::mean_impl<Sample, SumFeature> > +// : droppable_accumulator_base< +// with_cached_result<impl::mean_impl<Sample, SumFeature> > +// > +//{ +// template<typename Args> +// droppable_accumulator(Args const &args) +// : droppable_accumulator::base(args) +// { +// } +//}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/median.hpp b/boost/boost/accumulators/statistics/median.hpp new file mode 100644 index 0000000..d361c6d --- /dev/null +++ b/boost/boost/accumulators/statistics/median.hpp
@@ -0,0 +1,301 @@ +/////////////////////////////////////////////////////////////////////////////// +// median.hpp +// +// Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MEDIAN_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MEDIAN_HPP_EAN_28_10_2005 + +#include <boost/mpl/placeholders.hpp> +#include <boost/range/iterator_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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#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_cumul_dist.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // median_impl + // + /** + @brief Median estimation based on the \f$P^2\f$ quantile estimator + + The \f$P^2\f$ algorithm is invoked with a quantile probability of 0.5. + */ + template<typename Sample> + struct median_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + median_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + return p_square_quantile_for_median(args); + } + }; + /////////////////////////////////////////////////////////////////////////////// + // with_density_median_impl + // + /** + @brief Median estimation based on the density estimator + + The algorithm determines the bin in which the \f$0.5*cnt\f$-th sample lies, \f$cnt\f$ being + the total number of samples. It returns the approximate horizontal position of this sample, + based on a linear interpolation inside the bin. + */ + template<typename Sample> + struct with_density_median_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + typedef std::vector<std::pair<float_type, float_type> > histogram_type; + typedef iterator_range<typename histogram_type::iterator> range_type; + // for boost::result_of + typedef float_type result_type; + + template<typename Args> + with_density_median_impl(Args const &args) + : sum(numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , is_dirty(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty = true; + } + + + template<typename Args> + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + std::size_t cnt = count(args); + range_type histogram = density(args); + typename range_type::iterator it = histogram.begin(); + while (this->sum < 0.5 * cnt) + { + this->sum += it->second * cnt; + ++it; + } + --it; + float_type over = numeric::fdiv(this->sum - 0.5 * cnt, it->second * cnt); + this->median = it->first * over + (it + 1)->first * (1. - over); + } + + return this->median; + } + + private: + mutable float_type sum; + mutable bool is_dirty; + mutable float_type median; + }; + + /////////////////////////////////////////////////////////////////////////////// + // with_p_square_cumulative_distribution_median_impl + // + /** + @brief Median estimation based on the \f$P^2\f$ cumulative distribution estimator + + The algorithm determines the first (leftmost) bin with a height exceeding 0.5. It + returns the approximate horizontal position of where the cumulative distribution + equals 0.5, based on a linear interpolation inside the bin. + */ + template<typename Sample> + struct with_p_square_cumulative_distribution_median_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + typedef std::vector<std::pair<float_type, float_type> > histogram_type; + typedef iterator_range<typename histogram_type::iterator> range_type; + // for boost::result_of + typedef float_type result_type; + + with_p_square_cumulative_distribution_median_impl(dont_care) + : is_dirty(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty = true; + } + + template<typename Args> + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + range_type histogram = p_square_cumulative_distribution(args); + typename range_type::iterator it = histogram.begin(); + while (it->second < 0.5) + { + ++it; + } + float_type over = numeric::fdiv(it->second - 0.5, it->second - (it - 1)->second); + this->median = it->first * over + (it + 1)->first * ( 1. - over ); + } + + return this->median; + } + private: + + mutable bool is_dirty; + mutable float_type median; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::median +// tag::with_densisty_median +// tag::with_p_square_cumulative_distribution_median +// +namespace tag +{ + struct median + : depends_on<p_square_quantile_for_median> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::median_impl<mpl::_1> impl; + }; + struct with_density_median + : depends_on<count, density> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::with_density_median_impl<mpl::_1> impl; + }; + struct with_p_square_cumulative_distribution_median + : depends_on<p_square_cumulative_distribution> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::with_p_square_cumulative_distribution_median_impl<mpl::_1> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::median +// extract::with_density_median +// extract::with_p_square_cumulative_distribution_median +// +namespace extract +{ + extractor<tag::median> const median = {}; + extractor<tag::with_density_median> const with_density_median = {}; + extractor<tag::with_p_square_cumulative_distribution_median> const with_p_square_cumulative_distribution_median = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(median) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(with_density_median) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(with_p_square_cumulative_distribution_median) +} + +using extract::median; +using extract::with_density_median; +using extract::with_p_square_cumulative_distribution_median; + +// median(with_p_square_quantile) -> median +template<> +struct as_feature<tag::median(with_p_square_quantile)> +{ + typedef tag::median type; +}; + +// median(with_density) -> with_density_median +template<> +struct as_feature<tag::median(with_density)> +{ + typedef tag::with_density_median type; +}; + +// median(with_p_square_cumulative_distribution) -> with_p_square_cumulative_distribution_median +template<> +struct as_feature<tag::median(with_p_square_cumulative_distribution)> +{ + typedef tag::with_p_square_cumulative_distribution_median type; +}; + +// for the purposes of feature-based dependency resolution, +// with_density_median and with_p_square_cumulative_distribution_median +// provide the same feature as median +template<> +struct feature_of<tag::with_density_median> + : feature_of<tag::median> +{ +}; + +template<> +struct feature_of<tag::with_p_square_cumulative_distribution_median> + : feature_of<tag::median> +{ +}; + +// So that median can be automatically substituted with +// weighted_median when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::median> +{ + typedef tag::weighted_median type; +}; + +template<> +struct feature_of<tag::weighted_median> + : feature_of<tag::median> +{ +}; + +// So that with_density_median can be automatically substituted with +// with_density_weighted_median when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::with_density_median> +{ + typedef tag::with_density_weighted_median type; +}; + +template<> +struct feature_of<tag::with_density_weighted_median> + : feature_of<tag::with_density_median> +{ +}; + +// So that with_p_square_cumulative_distribution_median can be automatically substituted with +// with_p_square_cumulative_distribution_weighted_median when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::with_p_square_cumulative_distribution_median> +{ + typedef tag::with_p_square_cumulative_distribution_weighted_median type; +}; + +template<> +struct feature_of<tag::with_p_square_cumulative_distribution_weighted_median> + : feature_of<tag::with_p_square_cumulative_distribution_median> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/min.hpp b/boost/boost/accumulators/statistics/min.hpp new file mode 100644 index 0000000..83943bd --- /dev/null +++ b/boost/boost/accumulators/statistics/min.hpp
@@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////////// +// min.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MIN_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MIN_HPP_EAN_28_10_2005 + +#include <limits> +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // min_impl + template<typename Sample> + struct min_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + template<typename Args> + min_impl(Args const &args) + : min_(numeric::as_max(args[sample | Sample()])) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + numeric::min_assign(this->min_, args[sample]); + } + + result_type result(dont_care) const + { + return this->min_; + } + + private: + Sample min_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::min +// +namespace tag +{ + struct min + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::min_impl<mpl::_1> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::min +// +namespace extract +{ + extractor<tag::min> const min = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(min) +} + +using extract::min; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/moment.hpp b/boost/boost/accumulators/statistics/moment.hpp new file mode 100644 index 0000000..3dabd47 --- /dev/null +++ b/boost/boost/accumulators/statistics/moment.hpp
@@ -0,0 +1,125 @@ +/////////////////////////////////////////////////////////////////////////////// +// moment.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_MOMENT_HPP_EAN_15_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_MOMENT_HPP_EAN_15_11_2005 + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/mpl/int.hpp> +#include <boost/mpl/assert.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> + +namespace boost { namespace numeric +{ + /// INTERNAL ONLY + /// + template<typename T> + T const &pow(T const &x, mpl::int_<1>) + { + return x; + } + + /// INTERNAL ONLY + /// + template<typename T, int N> + T pow(T const &x, mpl::int_<N>) + { + using namespace operators; + T y = numeric::pow(x, mpl::int_<N/2>()); + T z = y * y; + return (N % 2) ? (z * x) : z; + } +}} + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // moment_impl + template<typename N, typename Sample> + struct moment_impl + : accumulator_base // TODO: also depends_on sum of powers + { + BOOST_MPL_ASSERT_RELATION(N::value, >, 0); + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + template<typename Args> + moment_impl(Args const &args) + : sum(args[sample | Sample()]) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + this->sum += numeric::pow(args[sample], N()); + } + + template<typename Args> + result_type result(Args const &args) const + { + return numeric::fdiv(this->sum, count(args)); + } + + private: + Sample sum; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::moment +// +namespace tag +{ + template<int N> + struct moment + : depends_on<count> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::moment_impl<mpl::int_<N>, mpl::_1> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::moment +// +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, moment, (int)) +} + +using extract::moment; + +// So that moment<N> can be automatically substituted with +// weighted_moment<N> when the weight parameter is non-void +template<int N> +struct as_weighted_feature<tag::moment<N> > +{ + typedef tag::weighted_moment<N> type; +}; + +template<int N> +struct feature_of<tag::weighted_moment<N> > + : feature_of<tag::moment<N> > +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/p_square_cumul_dist.hpp b/boost/boost/accumulators/statistics/p_square_cumul_dist.hpp new file mode 100644 index 0000000..5069283 --- /dev/null +++ b/boost/boost/accumulators/statistics/p_square_cumul_dist.hpp
@@ -0,0 +1,263 @@ +/////////////////////////////////////////////////////////////////////////////// +// 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/accumulators_fwd.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) + +BOOST_ACCUMULATORS_IGNORE_GLOBAL(p_square_cumulative_distribution_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 algorithm 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::fdiv<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::fdiv(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::fdiv(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
diff --git a/boost/boost/accumulators/statistics/p_square_cumulative_distribution.hpp b/boost/boost/accumulators/statistics/p_square_cumulative_distribution.hpp new file mode 100644 index 0000000..5e08b51 --- /dev/null +++ b/boost/boost/accumulators/statistics/p_square_cumulative_distribution.hpp
@@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////// +// p_square_cumulative_distribution.hpp +// +// 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_03_19_2012 +#define BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012 + +#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 + +#include <boost/accumulators/statistics/p_square_cumul_dist.hpp> + +#endif
diff --git a/boost/boost/accumulators/statistics/p_square_quantile.hpp b/boost/boost/accumulators/statistics/p_square_quantile.hpp new file mode 100644 index 0000000..636fea7 --- /dev/null +++ b/boost/boost/accumulators/statistics/p_square_quantile.hpp
@@ -0,0 +1,257 @@ +/////////////////////////////////////////////////////////////////////////////// +// p_square_quantile.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_P_SQUARE_QUANTILE_HPP_DE_01_01_2006 + +#include <cmath> +#include <functional> +#include <boost/array.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/parameter/keyword.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // p_square_quantile_impl + // single quantile estimation + /** + @brief Single quantile estimation with the \f$P^2\f$ algorithm + + The \f$P^2\f$ algorithm estimates a quantile dynamically without storing samples. Instead of + storing the whole sample cumulative distribution, only five points (markers) are stored. The heights + of these markers are the minimum and the maximum of the samples and the current estimates of the + \f$(p/2)\f$-, \f$p\f$- and \f$(1+p)/2\f$-quantiles. Their positions are equal to the number + of samples that are smaller or equal to the markers. Each time a new samples is recorded, the + positions of the markers are updated and if necessary their heights are adjusted using a piecewise- + parabolic formula. + + For further details, see + + R. Jain and I. Chlamtac, The P^2 algorithm for dynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param quantile_probability + */ + template<typename Sample, typename Impl> + struct p_square_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + typedef array<float_type, 5> array_type; + // for boost::result_of + typedef float_type result_type; + + template<typename Args> + p_square_quantile_impl(Args const &args) + : p(is_same<Impl, for_median>::value ? 0.5 : args[quantile_probability | 0.5]) + , heights() + , actual_positions() + , desired_positions() + , positions_increments() + { + for(std::size_t i = 0; i < 5; ++i) + { + this->actual_positions[i] = i + 1.; + } + + this->desired_positions[0] = 1.; + this->desired_positions[1] = 1. + 2. * this->p; + this->desired_positions[2] = 1. + 4. * this->p; + this->desired_positions[3] = 3. + 2. * this->p; + this->desired_positions[4] = 5.; + + this->positions_increments[0] = 0.; + this->positions_increments[1] = this->p / 2.; + this->positions_increments[2] = this->p; + this->positions_increments[3] = (1. + this->p) / 2.; + this->positions_increments[4] = 1.; + } + + template<typename Args> + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + // accumulate 5 first samples + if(cnt <= 5) + { + this->heights[cnt - 1] = args[sample]; + + // complete the initialization of heights by sorting + if(cnt == 5) + { + std::sort(this->heights.begin(), this->heights.end()); + } + } + else + { + std::size_t sample_cell = 1; // k + + // find cell k such that heights[k-1] <= args[sample] < heights[k] and adjust extreme values + if (args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + sample_cell = 1; + } + else if (this->heights[4] <= args[sample]) + { + this->heights[4] = args[sample]; + sample_cell = 4; + } + else + { + typedef typename array_type::iterator iterator; + iterator it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // update positions of markers above sample_cell + for(std::size_t i = sample_cell; i < 5; ++i) + { + ++this->actual_positions[i]; + } + + // update desired positions of all markers + for(std::size_t i = 0; i < 5; ++i) + { + this->desired_positions[i] += this->positions_increments[i]; + } + + // adjust heights and actual positions of markers 1 to 3 if necessary + for(std::size_t i = 1; i <= 3; ++i) + { + // offset to desired positions + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i + 1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i - 1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i + 1] - this->heights[i]) / dp; + float_type hm = (this->heights[i - 1] - this->heights[i]) / dm; + + if((d >= 1. && dp > 1.) || (d <= -1. && dm < -1.)) + { + short sign_d = static_cast<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; + } + } + } + } + + result_type result(dont_care) const + { + return this->heights[2]; + } + + private: + float_type p; // the quantile probability p + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // n'_i + array_type positions_increments; // dn'_i + }; + +} // namespace detail + +/////////////////////////////////////////////////////////////////////////////// +// tag::p_square_quantile +// +namespace tag +{ + struct p_square_quantile + : depends_on<count> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::p_square_quantile_impl<mpl::_1, regular> impl; + }; + struct p_square_quantile_for_median + : depends_on<count> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::p_square_quantile_impl<mpl::_1, for_median> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::p_square_quantile +// extract::p_square_quantile_for_median +// +namespace extract +{ + extractor<tag::p_square_quantile> const p_square_quantile = {}; + extractor<tag::p_square_quantile_for_median> const p_square_quantile_for_median = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(p_square_quantile) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(p_square_quantile_for_median) +} + +using extract::p_square_quantile; +using extract::p_square_quantile_for_median; + +// So that p_square_quantile can be automatically substituted with +// weighted_p_square_quantile when the weight parameter is non-void +template<> +struct as_weighted_feature<tag::p_square_quantile> +{ + typedef tag::weighted_p_square_quantile type; +}; + +template<> +struct feature_of<tag::weighted_p_square_quantile> + : feature_of<tag::p_square_quantile> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/parameters/quantile_probability.hpp b/boost/boost/accumulators/statistics/parameters/quantile_probability.hpp new file mode 100644 index 0000000..e879264 --- /dev/null +++ b/boost/boost/accumulators/statistics/parameters/quantile_probability.hpp
@@ -0,0 +1,23 @@ +/////////////////////////////////////////////////////////////////////////////// +// quantile_probability.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_PARAMETERS_QUANTILE_PROBABILITY_HPP_EAN_03_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_PARAMETERS_QUANTILE_PROBABILITY_HPP_EAN_03_11_2005 + +#include <boost/parameter/keyword.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> + +namespace boost { namespace accumulators +{ + +BOOST_PARAMETER_KEYWORD(tag, quantile_probability) + +BOOST_ACCUMULATORS_IGNORE_GLOBAL(quantile_probability) + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/peaks_over_threshold.hpp b/boost/boost/accumulators/statistics/peaks_over_threshold.hpp new file mode 100644 index 0000000..f04f743 --- /dev/null +++ b/boost/boost/accumulators/statistics/peaks_over_threshold.hpp
@@ -0,0 +1,405 @@ +/////////////////////////////////////////////////////////////////////////////// +// peaks_over_threshold.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006 + +#include <vector> +#include <limits> +#include <numeric> +#include <functional> +#include <boost/config/no_tr1/cmath.hpp> // pow +#include <sstream> // stringstream +#include <stdexcept> // runtime_error +#include <boost/throw_exception.hpp> +#include <boost/range.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/int.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/accumulators/accumulators_fwd.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/tail.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// threshold_probability and threshold named parameters +// +BOOST_PARAMETER_NESTED_KEYWORD(tag, pot_threshold_value, threshold_value) +BOOST_PARAMETER_NESTED_KEYWORD(tag, pot_threshold_probability, threshold_probability) + +BOOST_ACCUMULATORS_IGNORE_GLOBAL(pot_threshold_value) +BOOST_ACCUMULATORS_IGNORE_GLOBAL(pot_threshold_probability) + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // peaks_over_threshold_impl + // works with an explicit threshold value and does not depend on order statistics + /** + @brief Peaks over Threshold Method for Quantile and Tail Mean Estimation + + According to the theorem of Pickands-Balkema-de Haan, the distribution function \f$F_u(x)\f$ of + the excesses \f$x\f$ over some sufficiently high threshold \f$u\f$ of a distribution function \f$F(x)\f$ + may be approximated by a generalized Pareto distribution + \f[ + G_{\xi,\beta}(x) = + \left\{ + \begin{array}{ll} + \beta^{-1}\left(1+\frac{\xi x}{\beta}\right)^{-1/\xi-1} & \textrm{if }\xi\neq0\\ + \beta^{-1}\exp\left(-\frac{x}{\beta}\right) & \textrm{if }\xi=0, + \end{array} + \right. + \f] + with suitable parameters \f$\xi\f$ and \f$\beta\f$ that can be estimated, e.g., with the method of moments, cf. + Hosking and Wallis (1987), + \f[ + \begin{array}{lll} + \hat{\xi} & = & \frac{1}{2}\left[1-\frac{(\hat{\mu}-u)^2}{\hat{\sigma}^2}\right]\\ + \hat{\beta} & = & \frac{\hat{\mu}-u}{2}\left[\frac{(\hat{\mu}-u)^2}{\hat{\sigma}^2}+1\right], + \end{array} + \f] + \f$\hat{\mu}\f$ and \f$\hat{\sigma}^2\f$ being the empirical mean and variance of the samples over + the threshold \f$u\f$. Equivalently, the distribution function + \f$F_u(x-u)\f$ of the exceedances \f$x-u\f$ can be approximated by + \f$G_{\xi,\beta}(x-u)=G_{\xi,\beta,u}(x)\f$. Since for \f$x\geq u\f$ the distribution function \f$F(x)\f$ + can be written as + \f[ + F(x) = [1 - \P(X \leq u)]F_u(x - u) + \P(X \leq u) + \f] + and the probability \f$\P(X \leq u)\f$ can be approximated by the empirical distribution function + \f$F_n(u)\f$ evaluated at \f$u\f$, an estimator of \f$F(x)\f$ is given by + \f[ + \widehat{F}(x) = [1 - F_n(u)]G_{\xi,\beta,u}(x) + F_n(u). + \f] + It can be shown that \f$\widehat{F}(x)\f$ is a generalized + Pareto distribution \f$G_{\xi,\bar{\beta},\bar{u}}(x)\f$ with \f$\bar{\beta}=\beta[1-F_n(u)]^{\xi}\f$ + and \f$\bar{u}=u-\bar{\beta}\left\{[1-F_n(u)]^{-\xi}-1\right\}/\xi\f$. By inverting \f$\widehat{F}(x)\f$, + one obtains an estimator for the \f$\alpha\f$-quantile, + \f[ + \hat{q}_{\alpha} = \bar{u} + \frac{\bar{\beta}}{\xi}\left[(1-\alpha)^{-\xi}-1\right], + \f] + and similarly an estimator for the (coherent) tail mean, + \f[ + \widehat{CTM}_{\alpha} = \hat{q}_{\alpha} - \frac{\bar{\beta}}{\xi-1}(1-\alpha)^{-\xi}, + \f] + cf. McNeil and Frey (2000). + + Note that in case extreme values of the left tail are fitted, the distribution is mirrored with respect to the + \f$y\f$ axis such that the left tail can be treated as a right tail. The computed fit parameters thus define + the Pareto distribution that fits the mirrored left tail. When quantities like a quantile or a tail mean are + computed using the fit parameters obtained from the mirrored data, the result is mirrored back, yielding the + correct result. + + For further details, see + + J. R. M. Hosking and J. R. Wallis, Parameter and quantile estimation for the generalized Pareto distribution, + Technometrics, Volume 29, 1987, p. 339-349 + + A. J. McNeil and R. Frey, Estimation of Tail-Related Risk Measures for Heteroscedastic Financial Time Series: + an Extreme Value Approach, Journal of Empirical Finance, Volume 7, 2000, p. 271-300 + + @param quantile_probability + @param pot_threshold_value + */ + template<typename Sample, typename LeftRight> + struct peaks_over_threshold_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + // for boost::result_of + typedef boost::tuple<float_type, float_type, float_type> result_type; + // for left tail fitting, mirror the extreme values + typedef mpl::int_<is_same<LeftRight, left>::value ? -1 : 1> sign; + + template<typename Args> + peaks_over_threshold_impl(Args const &args) + : Nu_(0) + , mu_(sign::value * numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , sigma2_(numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , threshold_(sign::value * args[pot_threshold_value]) + , fit_parameters_(boost::make_tuple(0., 0., 0.)) + , is_dirty_(true) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + this->is_dirty_ = true; + + if (sign::value * args[sample] > this->threshold_) + { + this->mu_ += args[sample]; + this->sigma2_ += args[sample] * args[sample]; + ++this->Nu_; + } + } + + template<typename Args> + result_type result(Args const &args) const + { + if (this->is_dirty_) + { + this->is_dirty_ = false; + + std::size_t cnt = count(args); + + this->mu_ = sign::value * numeric::fdiv(this->mu_, this->Nu_); + this->sigma2_ = numeric::fdiv(this->sigma2_, this->Nu_); + this->sigma2_ -= this->mu_ * this->mu_; + + float_type threshold_probability = numeric::fdiv(cnt - this->Nu_, cnt); + + float_type tmp = numeric::fdiv(( this->mu_ - this->threshold_ )*( this->mu_ - this->threshold_ ), this->sigma2_); + float_type xi_hat = 0.5 * ( 1. - tmp ); + float_type beta_hat = 0.5 * ( this->mu_ - this->threshold_ ) * ( 1. + tmp ); + float_type beta_bar = beta_hat * std::pow(1. - threshold_probability, xi_hat); + float_type u_bar = this->threshold_ - beta_bar * ( std::pow(1. - threshold_probability, -xi_hat) - 1.)/xi_hat; + this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat); + } + + return this->fit_parameters_; + } + + private: + std::size_t Nu_; // number of samples larger than threshold + mutable float_type mu_; // mean of Nu_ largest samples + mutable float_type sigma2_; // variance of Nu_ largest samples + float_type threshold_; + mutable result_type fit_parameters_; // boost::tuple that stores fit parameters + mutable bool is_dirty_; + }; + + /////////////////////////////////////////////////////////////////////////////// + // peaks_over_threshold_prob_impl + // determines threshold from a given threshold probability using order statistics + /** + @brief Peaks over Threshold Method for Quantile and Tail Mean Estimation + + @sa peaks_over_threshold_impl + + @param quantile_probability + @param pot_threshold_probability + */ + template<typename Sample, typename LeftRight> + struct peaks_over_threshold_prob_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + // for boost::result_of + typedef boost::tuple<float_type, float_type, float_type> result_type; + // for left tail fitting, mirror the extreme values + typedef mpl::int_<is_same<LeftRight, left>::value ? -1 : 1> sign; + + template<typename Args> + peaks_over_threshold_prob_impl(Args const &args) + : mu_(sign::value * numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , sigma2_(numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , threshold_probability_(args[pot_threshold_probability]) + , fit_parameters_(boost::make_tuple(0., 0., 0.)) + , is_dirty_(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty_ = true; + } + + template<typename Args> + result_type result(Args const &args) const + { + if (this->is_dirty_) + { + this->is_dirty_ = false; + + std::size_t cnt = count(args); + + // the n'th cached sample provides an approximate threshold value u + std::size_t n = static_cast<std::size_t>( + std::ceil( + cnt * ( ( is_same<LeftRight, left>::value ) ? this->threshold_probability_ : 1. - this->threshold_probability_ ) + ) + ); + + // If n is in a valid range, return result, otherwise return NaN or throw exception + if ( n >= static_cast<std::size_t>(tail(args).size())) + { + if (std::numeric_limits<float_type>::has_quiet_NaN) + { + return boost::make_tuple( + std::numeric_limits<float_type>::quiet_NaN() + , std::numeric_limits<float_type>::quiet_NaN() + , std::numeric_limits<float_type>::quiet_NaN() + ); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return boost::make_tuple(Sample(0), Sample(0), Sample(0)); + } + } + else + { + float_type u = *(tail(args).begin() + n - 1) * sign::value; + + // compute mean and variance of samples above/under threshold value u + for (std::size_t i = 0; i < n; ++i) + { + mu_ += *(tail(args).begin() + i); + sigma2_ += *(tail(args).begin() + i) * (*(tail(args).begin() + i)); + } + + this->mu_ = sign::value * numeric::fdiv(this->mu_, n); + this->sigma2_ = numeric::fdiv(this->sigma2_, n); + this->sigma2_ -= this->mu_ * this->mu_; + + if (is_same<LeftRight, left>::value) + this->threshold_probability_ = 1. - this->threshold_probability_; + + float_type tmp = numeric::fdiv(( this->mu_ - u )*( this->mu_ - u ), this->sigma2_); + float_type xi_hat = 0.5 * ( 1. - tmp ); + float_type beta_hat = 0.5 * ( this->mu_ - u ) * ( 1. + tmp ); + float_type beta_bar = beta_hat * std::pow(1. - threshold_probability_, xi_hat); + float_type u_bar = u - beta_bar * ( std::pow(1. - threshold_probability_, -xi_hat) - 1.)/xi_hat; + this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat); + } + } + + return this->fit_parameters_; + } + + private: + mutable float_type mu_; // mean of samples above threshold u + mutable float_type sigma2_; // variance of samples above threshold u + mutable float_type threshold_probability_; + mutable result_type fit_parameters_; // boost::tuple that stores fit parameters + mutable bool is_dirty_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::peaks_over_threshold +// +namespace tag +{ + template<typename LeftRight> + struct peaks_over_threshold + : depends_on<count> + , pot_threshold_value + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::peaks_over_threshold_impl<mpl::_1, LeftRight> impl; + }; + + template<typename LeftRight> + struct peaks_over_threshold_prob + : depends_on<count, tail<LeftRight> > + , pot_threshold_probability + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::peaks_over_threshold_prob_impl<mpl::_1, LeftRight> impl; + }; + + struct abstract_peaks_over_threshold + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::peaks_over_threshold +// +namespace extract +{ + extractor<tag::abstract_peaks_over_threshold> const peaks_over_threshold = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(peaks_over_threshold) +} + +using extract::peaks_over_threshold; + +// peaks_over_threshold<LeftRight>(with_threshold_value) -> peaks_over_threshold<LeftRight> +template<typename LeftRight> +struct as_feature<tag::peaks_over_threshold<LeftRight>(with_threshold_value)> +{ + typedef tag::peaks_over_threshold<LeftRight> type; +}; + +// peaks_over_threshold<LeftRight>(with_threshold_probability) -> peaks_over_threshold_prob<LeftRight> +template<typename LeftRight> +struct as_feature<tag::peaks_over_threshold<LeftRight>(with_threshold_probability)> +{ + typedef tag::peaks_over_threshold_prob<LeftRight> type; +}; + +template<typename LeftRight> +struct feature_of<tag::peaks_over_threshold<LeftRight> > + : feature_of<tag::abstract_peaks_over_threshold> +{ +}; + +template<typename LeftRight> +struct feature_of<tag::peaks_over_threshold_prob<LeftRight> > + : feature_of<tag::abstract_peaks_over_threshold> +{ +}; + +// So that peaks_over_threshold can be automatically substituted +// with weighted_peaks_over_threshold when the weight parameter is non-void. +template<typename LeftRight> +struct as_weighted_feature<tag::peaks_over_threshold<LeftRight> > +{ + typedef tag::weighted_peaks_over_threshold<LeftRight> type; +}; + +template<typename LeftRight> +struct feature_of<tag::weighted_peaks_over_threshold<LeftRight> > + : feature_of<tag::peaks_over_threshold<LeftRight> > +{}; + +// So that peaks_over_threshold_prob can be automatically substituted +// with weighted_peaks_over_threshold_prob when the weight parameter is non-void. +template<typename LeftRight> +struct as_weighted_feature<tag::peaks_over_threshold_prob<LeftRight> > +{ + typedef tag::weighted_peaks_over_threshold_prob<LeftRight> type; +}; + +template<typename LeftRight> +struct feature_of<tag::weighted_peaks_over_threshold_prob<LeftRight> > + : feature_of<tag::peaks_over_threshold_prob<LeftRight> > +{}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif
diff --git a/boost/boost/accumulators/statistics/pot_quantile.hpp b/boost/boost/accumulators/statistics/pot_quantile.hpp new file mode 100644 index 0000000..470bdba --- /dev/null +++ b/boost/boost/accumulators/statistics/pot_quantile.hpp
@@ -0,0 +1,205 @@ +/////////////////////////////////////////////////////////////////////////////// +// pot_quantile.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_POT_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_POT_QUANTILE_HPP_DE_01_01_2006 + +#include <vector> +#include <limits> +#include <numeric> +#include <functional> +#include <boost/parameter/keyword.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/mpl/if.hpp> +#include <boost/type_traits/is_same.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/tail.hpp> +#include <boost/accumulators/statistics/peaks_over_threshold.hpp> +#include <boost/accumulators/statistics/weighted_peaks_over_threshold.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // pot_quantile_impl + // + /** + @brief Quantile Estimation based on Peaks over Threshold Method (for both left and right tails) + + Computes an estimate + \f[ + \hat{q}_{\alpha} = \bar{u} + \frac{\bar{\beta}}{\xi}\left[(1-\alpha)^{-\xi}-1\right] + \f] + for a right or left extreme quantile, \f$\bar[u]\f$, \f$\bar{\beta}\f$ and \f$\xi\f$ being the parameters of the + generalized Pareto distribution that approximates the right tail of the distribution (or the mirrored left tail, + in case the left tail is used). In the latter case, the result is mirrored back, yielding the correct result. + */ + template<typename Sample, typename Impl, typename LeftRight> + struct pot_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + // for boost::result_of + typedef float_type result_type; + + pot_quantile_impl(dont_care) + : sign_((is_same<LeftRight, left>::value) ? -1 : 1) + { + } + + template<typename Args> + result_type result(Args const &args) const + { + typedef + typename mpl::if_< + is_same<Impl, weighted> + , tag::weighted_peaks_over_threshold<LeftRight> + , tag::peaks_over_threshold<LeftRight> + >::type + peaks_over_threshold_tag; + + extractor<peaks_over_threshold_tag> const some_peaks_over_threshold = {}; + + float_type u_bar = some_peaks_over_threshold(args).template get<0>(); + float_type beta_bar = some_peaks_over_threshold(args).template get<1>(); + float_type xi_hat = some_peaks_over_threshold(args).template get<2>(); + + return this->sign_ * (u_bar + beta_bar/xi_hat * ( std::pow( + is_same<LeftRight, left>::value ? args[quantile_probability] : 1. - args[quantile_probability] + , -xi_hat + ) - 1.)); + } + + private: + short sign_; // if the fit parameters from the mirrored left tail extreme values are used, mirror back the result + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::pot_quantile<> +// tag::pot_quantile_prob<> +// tag::weighted_pot_quantile<> +// tag::weighted_pot_quantile_prob<> +// +namespace tag +{ + template<typename LeftRight> + struct pot_quantile + : depends_on<peaks_over_threshold<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_quantile_impl<mpl::_1, unweighted, LeftRight> impl; + }; + template<typename LeftRight> + struct pot_quantile_prob + : depends_on<peaks_over_threshold_prob<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_quantile_impl<mpl::_1, unweighted, LeftRight> impl; + }; + template<typename LeftRight> + struct weighted_pot_quantile + : depends_on<weighted_peaks_over_threshold<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_quantile_impl<mpl::_1, weighted, LeftRight> impl; + }; + template<typename LeftRight> + struct weighted_pot_quantile_prob + : depends_on<weighted_peaks_over_threshold_prob<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_quantile_impl<mpl::_1, weighted, LeftRight> impl; + }; +} + +// pot_quantile<LeftRight>(with_threshold_value) -> pot_quantile<LeftRight> +template<typename LeftRight> +struct as_feature<tag::pot_quantile<LeftRight>(with_threshold_value)> +{ + typedef tag::pot_quantile<LeftRight> type; +}; + +// pot_quantile<LeftRight>(with_threshold_probability) -> pot_quantile_prob<LeftRight> +template<typename LeftRight> +struct as_feature<tag::pot_quantile<LeftRight>(with_threshold_probability)> +{ + typedef tag::pot_quantile_prob<LeftRight> type; +}; + +// weighted_pot_quantile<LeftRight>(with_threshold_value) -> weighted_pot_quantile<LeftRight> +template<typename LeftRight> +struct as_feature<tag::weighted_pot_quantile<LeftRight>(with_threshold_value)> +{ + typedef tag::weighted_pot_quantile<LeftRight> type; +}; + +// weighted_pot_quantile<LeftRight>(with_threshold_probability) -> weighted_pot_quantile_prob<LeftRight> +template<typename LeftRight> +struct as_feature<tag::weighted_pot_quantile<LeftRight>(with_threshold_probability)> +{ + typedef tag::weighted_pot_quantile_prob<LeftRight> type; +}; + +// for the purposes of feature-based dependency resolution, +// pot_quantile<LeftRight> and pot_quantile_prob<LeftRight> provide +// the same feature as quantile +template<typename LeftRight> +struct feature_of<tag::pot_quantile<LeftRight> > + : feature_of<tag::quantile> +{ +}; + +template<typename LeftRight> +struct feature_of<tag::pot_quantile_prob<LeftRight> > + : feature_of<tag::quantile> +{ +}; + +// So that pot_quantile can be automatically substituted +// with weighted_pot_quantile when the weight parameter is non-void. +template<typename LeftRight> +struct as_weighted_feature<tag::pot_quantile<LeftRight> > +{ + typedef tag::weighted_pot_quantile<LeftRight> type; +}; + +template<typename LeftRight> +struct feature_of<tag::weighted_pot_quantile<LeftRight> > + : feature_of<tag::pot_quantile<LeftRight> > +{ +}; + +// So that pot_quantile_prob can be automatically substituted +// with weighted_pot_quantile_prob when the weight parameter is non-void. +template<typename LeftRight> +struct as_weighted_feature<tag::pot_quantile_prob<LeftRight> > +{ + typedef tag::weighted_pot_quantile_prob<LeftRight> type; +}; + +template<typename LeftRight> +struct feature_of<tag::weighted_pot_quantile_prob<LeftRight> > + : feature_of<tag::pot_quantile_prob<LeftRight> > +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/pot_tail_mean.hpp b/boost/boost/accumulators/statistics/pot_tail_mean.hpp new file mode 100644 index 0000000..a78043f --- /dev/null +++ b/boost/boost/accumulators/statistics/pot_tail_mean.hpp
@@ -0,0 +1,211 @@ +/////////////////////////////////////////////////////////////////////////////// +// pot_tail_mean.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_POT_TAIL_MEAN_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_POT_TAIL_MEAN_HPP_DE_01_01_2006 + +#include <vector> +#include <limits> +#include <numeric> +#include <functional> +#include <boost/range.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/type_traits/is_same.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/peaks_over_threshold.hpp> +#include <boost/accumulators/statistics/weighted_peaks_over_threshold.hpp> +#include <boost/accumulators/statistics/pot_quantile.hpp> +#include <boost/accumulators/statistics/tail_mean.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // pot_tail_mean_impl + // + /** + @brief Estimation of the (coherent) tail mean based on the peaks over threshold method (for both left and right tails) + + Computes an estimate for the (coherent) tail mean + \f[ + \widehat{CTM}_{\alpha} = \hat{q}_{\alpha} - \frac{\bar{\beta}}{\xi-1}(1-\alpha)^{-\xi}, + \f] + where \f$\bar[u]\f$, \f$\bar{\beta}\f$ and \f$\xi\f$ are the parameters of the + generalized Pareto distribution that approximates the right tail of the distribution (or the + mirrored left tail, in case the left tail is used). In the latter case, the result is mirrored + back, yielding the correct result. + */ + template<typename Sample, typename Impl, typename LeftRight> + struct pot_tail_mean_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + // for boost::result_of + typedef float_type result_type; + + pot_tail_mean_impl(dont_care) + : sign_((is_same<LeftRight, left>::value) ? -1 : 1) + { + } + + template<typename Args> + result_type result(Args const &args) const + { + typedef + typename mpl::if_< + is_same<Impl, weighted> + , tag::weighted_peaks_over_threshold<LeftRight> + , tag::peaks_over_threshold<LeftRight> + >::type + peaks_over_threshold_tag; + + typedef + typename mpl::if_< + is_same<Impl, weighted> + , tag::weighted_pot_quantile<LeftRight> + , tag::pot_quantile<LeftRight> + >::type + pot_quantile_tag; + + extractor<peaks_over_threshold_tag> const some_peaks_over_threshold = {}; + extractor<pot_quantile_tag> const some_pot_quantile = {}; + + float_type beta_bar = some_peaks_over_threshold(args).template get<1>(); + float_type xi_hat = some_peaks_over_threshold(args).template get<2>(); + + return some_pot_quantile(args) - this->sign_ * beta_bar/( xi_hat - 1. ) * std::pow( + is_same<LeftRight, left>::value ? args[quantile_probability] : 1. - args[quantile_probability] + , -xi_hat); + } + private: + short sign_; // if the fit parameters from the mirrored left tail extreme values are used, mirror back the result + }; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::pot_tail_mean +// tag::pot_tail_mean_prob +// +namespace tag +{ + template<typename LeftRight> + struct pot_tail_mean + : depends_on<peaks_over_threshold<LeftRight>, pot_quantile<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_tail_mean_impl<mpl::_1, unweighted, LeftRight> impl; + }; + template<typename LeftRight> + struct pot_tail_mean_prob + : depends_on<peaks_over_threshold_prob<LeftRight>, pot_quantile_prob<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_tail_mean_impl<mpl::_1, unweighted, LeftRight> impl; + }; + template<typename LeftRight> + struct weighted_pot_tail_mean + : depends_on<weighted_peaks_over_threshold<LeftRight>, weighted_pot_quantile<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_tail_mean_impl<mpl::_1, weighted, LeftRight> impl; + }; + template<typename LeftRight> + struct weighted_pot_tail_mean_prob + : depends_on<weighted_peaks_over_threshold_prob<LeftRight>, weighted_pot_quantile_prob<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::pot_tail_mean_impl<mpl::_1, weighted, LeftRight> impl; + }; +} + +// pot_tail_mean<LeftRight>(with_threshold_value) -> pot_tail_mean<LeftRight> +template<typename LeftRight> +struct as_feature<tag::pot_tail_mean<LeftRight>(with_threshold_value)> +{ + typedef tag::pot_tail_mean<LeftRight> type; +}; + +// pot_tail_mean<LeftRight>(with_threshold_probability) -> pot_tail_mean_prob<LeftRight> +template<typename LeftRight> +struct as_feature<tag::pot_tail_mean<LeftRight>(with_threshold_probability)> +{ + typedef tag::pot_tail_mean_prob<LeftRight> type; +}; + +// weighted_pot_tail_mean<LeftRight>(with_threshold_value) -> weighted_pot_tail_mean<LeftRight> +template<typename LeftRight> +struct as_feature<tag::weighted_pot_tail_mean<LeftRight>(with_threshold_value)> +{ + typedef tag::weighted_pot_tail_mean<LeftRight> type; +}; + +// weighted_pot_tail_mean<LeftRight>(with_threshold_probability) -> weighted_pot_tail_mean_prob<LeftRight> +template<typename LeftRight> +struct as_feature<tag::weighted_pot_tail_mean<LeftRight>(with_threshold_probability)> +{ + typedef tag::weighted_pot_tail_mean_prob<LeftRight> type; +}; + +// for the purposes of feature-based dependency resolution, +// pot_tail_mean<LeftRight> and pot_tail_mean_prob<LeftRight> provide +// the same feature as tail_mean +template<typename LeftRight> +struct feature_of<tag::pot_tail_mean<LeftRight> > + : feature_of<tag::tail_mean> +{ +}; + +template<typename LeftRight> +struct feature_of<tag::pot_tail_mean_prob<LeftRight> > + : feature_of<tag::tail_mean> +{ +}; + +// So that pot_tail_mean can be automatically substituted +// with weighted_pot_tail_mean when the weight parameter is non-void. +template<typename LeftRight> +struct as_weighted_feature<tag::pot_tail_mean<LeftRight> > +{ + typedef tag::weighted_pot_tail_mean<LeftRight> type; +}; + +template<typename LeftRight> +struct feature_of<tag::weighted_pot_tail_mean<LeftRight> > + : feature_of<tag::pot_tail_mean<LeftRight> > +{ +}; + +// So that pot_tail_mean_prob can be automatically substituted +// with weighted_pot_tail_mean_prob when the weight parameter is non-void. +template<typename LeftRight> +struct as_weighted_feature<tag::pot_tail_mean_prob<LeftRight> > +{ + typedef tag::weighted_pot_tail_mean_prob<LeftRight> type; +}; + +template<typename LeftRight> +struct feature_of<tag::weighted_pot_tail_mean_prob<LeftRight> > + : feature_of<tag::pot_tail_mean_prob<LeftRight> > +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/rolling_count.hpp b/boost/boost/accumulators/statistics/rolling_count.hpp new file mode 100644 index 0000000..1e34f76 --- /dev/null +++ b/boost/boost/accumulators/statistics/rolling_count.hpp
@@ -0,0 +1,80 @@ +/////////////////////////////////////////////////////////////////////////////// +// rolling_count.hpp +// +// Copyright 2008 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_ROLLING_COUNT_HPP_EAN_26_12_2008 +#define BOOST_ACCUMULATORS_STATISTICS_ROLLING_COUNT_HPP_EAN_26_12_2008 + +#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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/rolling_window.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + /////////////////////////////////////////////////////////////////////////////// + // rolling_count_impl + // returns the count of elements in the rolling window + template<typename Sample> + struct rolling_count_impl + : accumulator_base + { + typedef std::size_t result_type; + + rolling_count_impl(dont_care) + {} + + template<typename Args> + result_type result(Args const &args) const + { + return static_cast<std::size_t>(rolling_window_plus1(args).size()) - is_rolling_window_plus1_full(args); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::rolling_count +// +namespace tag +{ + struct rolling_count + : depends_on< rolling_window_plus1 > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::rolling_count_impl< mpl::_1 > impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword<tag::rolling_window_size> const window_size; + #endif + }; +} // namespace tag + +/////////////////////////////////////////////////////////////////////////////// +// extract::rolling_count +// +namespace extract +{ + extractor<tag::rolling_count> const rolling_count = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_count) +} + +using extract::rolling_count; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/rolling_mean.hpp b/boost/boost/accumulators/statistics/rolling_mean.hpp new file mode 100644 index 0000000..1439da1 --- /dev/null +++ b/boost/boost/accumulators/statistics/rolling_mean.hpp
@@ -0,0 +1,179 @@ +/////////////////////////////////////////////////////////////////////////////// +// rolling_mean.hpp +// Copyright (C) 2008 Eric Niebler. +// Copyright (C) 2012 Pieter Bastiaan Ober (Integricom). +// Distributed under the Boost Software 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_ROLLING_MEAN_HPP_EAN_26_12_2008 +#define BOOST_ACCUMULATORS_STATISTICS_ROLLING_MEAN_HPP_EAN_26_12_2008 + +#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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/rolling_sum.hpp> +#include <boost/accumulators/statistics/rolling_count.hpp> + +namespace boost { namespace accumulators +{ + namespace impl + { + /////////////////////////////////////////////////////////////////////////////// + // lazy_rolling_mean_impl + // returns the mean over the rolling window and is calculated only + // when the result is requested + template<typename Sample> + struct lazy_rolling_mean_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t, void, void>::result_type result_type; + + lazy_rolling_mean_impl(dont_care) + { + } + + template<typename Args> + result_type result(Args const &args) const + { + return numeric::fdiv(rolling_sum(args), rolling_count(args)); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // immediate_rolling_mean_impl + // The non-lazy version computes the rolling mean recursively when a new + // sample is added + template<typename Sample> + struct immediate_rolling_mean_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + template<typename Args> + immediate_rolling_mean_impl(Args const &args) + : mean_(numeric::fdiv(args[sample | Sample()],numeric::one<std::size_t>::value)) + { + } + + template<typename Args> + void operator()(Args const &args) + { + if(is_rolling_window_plus1_full(args)) + { + mean_ += numeric::fdiv(args[sample]-rolling_window_plus1(args).front(),rolling_count(args)); + } + else + { + result_type prev_mean = mean_; + mean_ += numeric::fdiv(args[sample]-prev_mean,rolling_count(args)); + } + } + + template<typename Args> + result_type result(Args const &) const + { + return mean_; + } + + private: + + result_type mean_; + }; + } // namespace impl + + /////////////////////////////////////////////////////////////////////////////// + // tag::lazy_rolling_mean + // tag::immediate_rolling_mean + // tag::rolling_mean + // + namespace tag + { + struct lazy_rolling_mean + : depends_on< rolling_sum, rolling_count > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::lazy_rolling_mean_impl< mpl::_1 > impl; + +#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword<tag::rolling_window_size> const window_size; +#endif + }; + + struct immediate_rolling_mean + : depends_on< rolling_window_plus1, rolling_count> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_rolling_mean_impl< mpl::_1> impl; + +#ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword<tag::rolling_window_size> const window_size; +#endif + }; + + // make immediate_rolling_mean the default implementation + struct rolling_mean : immediate_rolling_mean {}; + } // namespace tag + + /////////////////////////////////////////////////////////////////////////////// + // extract::lazy_rolling_mean + // extract::immediate_rolling_mean + // extract::rolling_mean + // + namespace extract + { + extractor<tag::lazy_rolling_mean> const lazy_rolling_mean = {}; + extractor<tag::immediate_rolling_mean> const immediate_rolling_mean = {}; + extractor<tag::rolling_mean> const rolling_mean = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(lazy_rolling_mean) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(immediate_rolling_mean) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_mean) + } + + using extract::lazy_rolling_mean; + using extract::immediate_rolling_mean; + using extract::rolling_mean; + + // rolling_mean(lazy) -> lazy_rolling_mean + template<> + struct as_feature<tag::rolling_mean(lazy)> + { + typedef tag::lazy_rolling_mean type; + }; + + // rolling_mean(immediate) -> immediate_rolling_mean + template<> + struct as_feature<tag::rolling_mean(immediate)> + { + typedef tag::immediate_rolling_mean type; + }; + + // for the purposes of feature-based dependency resolution, + // immediate_rolling_mean provides the same feature as rolling_mean + template<> + struct feature_of<tag::immediate_rolling_mean> + : feature_of<tag::rolling_mean> + { + }; + + // for the purposes of feature-based dependency resolution, + // lazy_rolling_mean provides the same feature as rolling_mean + template<> + struct feature_of<tag::lazy_rolling_mean> + : feature_of<tag::rolling_mean> + { + }; +}} // namespace boost::accumulators + +#endif \ No newline at end of file
diff --git a/boost/boost/accumulators/statistics/rolling_moment.hpp b/boost/boost/accumulators/statistics/rolling_moment.hpp new file mode 100644 index 0000000..f172cee --- /dev/null +++ b/boost/boost/accumulators/statistics/rolling_moment.hpp
@@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////////// +// rolling_moment.hpp +// Copyright 2005 Eric Niebler. +// Copyright (C) 2014 Pieter Bastiaan Ober (Integricom). +// Distributed under the Boost Software 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_ROLLING_MOMENT_HPP_EAN_27_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_ROLLING_MOMENT_HPP_EAN_27_11_2005 + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/mpl/int.hpp> +#include <boost/mpl/assert.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/moment.hpp> +#include <boost/accumulators/statistics/rolling_count.hpp> + +namespace boost { namespace accumulators +{ +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // rolling_moment_impl + template<typename N, typename Sample> + struct rolling_moment_impl + : accumulator_base + { + BOOST_MPL_ASSERT_RELATION(N::value, >, 0); + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t,void,void>::result_type result_type; + + template<typename Args> + rolling_moment_impl(Args const &args) + : sum_(args[sample | Sample()]) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + if(is_rolling_window_plus1_full(args)) + { + this->sum_ -= numeric::pow(rolling_window_plus1(args).front(), N()); + } + this->sum_ += numeric::pow(args[sample], N()); + } + + template<typename Args> + result_type result(Args const &args) const + { + return numeric::fdiv(this->sum_, rolling_count(args)); + } + + private: + result_type sum_; + }; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::rolling_moment +// +namespace tag +{ + template<int N> + struct rolling_moment + : depends_on< rolling_window_plus1, rolling_count> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::rolling_moment_impl<mpl::int_<N>, mpl::_1> impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword<tag::rolling_window_size> const window_size; + #endif + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::rolling_moment +// +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, rolling_moment, (int)) +} + +using extract::rolling_moment; + +// There is no weighted_rolling_moment (yet)... +// +//// So that rolling_moment<N> can be automatically substituted with +//// weighted_rolling_moment<N> when the weight parameter is non-void +//template<int N> +//struct as_weighted_feature<tag::rolling_moment<N> > +//{ +// typedef tag::weighted_rolling_moment<N> type; +//}; +// +//template<int N> +//struct feature_of<tag::weighted_rolling_moment<N> > +// : feature_of<tag::rolling_moment<N> > +//{ +//}; +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/rolling_sum.hpp b/boost/boost/accumulators/statistics/rolling_sum.hpp new file mode 100644 index 0000000..bbb7a8e --- /dev/null +++ b/boost/boost/accumulators/statistics/rolling_sum.hpp
@@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////////////////////// +// rolling_sum.hpp +// +// Copyright 2008 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_ROLLING_SUM_HPP_EAN_26_12_2008 +#define BOOST_ACCUMULATORS_STATISTICS_ROLLING_SUM_HPP_EAN_26_12_2008 + +#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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/rolling_window.hpp> + +namespace boost { namespace accumulators +{ +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // rolling_sum_impl + // returns the sum of the samples in the rolling window + template<typename Sample> + struct rolling_sum_impl + : accumulator_base + { + typedef Sample result_type; + + template<typename Args> + rolling_sum_impl(Args const &args) + : sum_(args[sample | Sample()]) + {} + + template<typename Args> + void operator ()(Args const &args) + { + if(is_rolling_window_plus1_full(args)) + { + this->sum_ -= rolling_window_plus1(args).front(); + } + this->sum_ += args[sample]; + } + + template<typename Args> + result_type result(Args const & /*args*/) const + { + return this->sum_; + } + + private: + Sample sum_; + }; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::rolling_sum +// +namespace tag +{ + struct rolling_sum + : depends_on< rolling_window_plus1 > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::rolling_sum_impl< mpl::_1 > impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword<tag::rolling_window_size> const window_size; + #endif + }; +} // namespace tag + +/////////////////////////////////////////////////////////////////////////////// +// extract::rolling_sum +// +namespace extract +{ + extractor<tag::rolling_sum> const rolling_sum = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_sum) +} + +using extract::rolling_sum; +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/rolling_variance.hpp b/boost/boost/accumulators/statistics/rolling_variance.hpp new file mode 100644 index 0000000..33b3922 --- /dev/null +++ b/boost/boost/accumulators/statistics/rolling_variance.hpp
@@ -0,0 +1,247 @@ +/////////////////////////////////////////////////////////////////////////////// +// rolling_variance.hpp +// Copyright (C) 2005 Eric Niebler +// Copyright (C) 2014 Pieter Bastiaan Ober (Integricom). +// Distributed under the Boost Software 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_ROLLING_VARIANCE_HPP_EAN_15_11_2011 +#define BOOST_ACCUMULATORS_STATISTICS_ROLLING_VARIANCE_HPP_EAN_15_11_2011 + +#include <boost/accumulators/accumulators.hpp> +#include <boost/accumulators/statistics/stats.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/rolling_mean.hpp> +#include <boost/accumulators/statistics/rolling_moment.hpp> + +#include <boost/type_traits/is_arithmetic.hpp> +#include <boost/utility/enable_if.hpp> + +namespace boost { namespace accumulators +{ +namespace impl +{ + //! Immediate (lazy) calculation of the rolling variance. + /*! + Calculation of sample variance \f$\sigma_n^2\f$ is done as follows, see also + http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance. + For a rolling window of size \f$N\f$, when \f$n <= N\f$, the variance is computed according to the formula + \f[ + \sigma_n^2 = \frac{1}{n-1} \sum_{i = 1}^n (x_i - \mu_n)^2. + \f] + When \f$n > N\f$, the sample variance over the window becomes: + \f[ + \sigma_n^2 = \frac{1}{N-1} \sum_{i = n-N+1}^n (x_i - \mu_n)^2. + \f] + */ + /////////////////////////////////////////////////////////////////////////////// + // lazy_rolling_variance_impl + // + template<typename Sample> + struct lazy_rolling_variance_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t,void,void>::result_type result_type; + + lazy_rolling_variance_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + result_type mean = rolling_mean(args); + size_t nr_samples = rolling_count(args); + if (nr_samples < 2) return result_type(); + return nr_samples*(rolling_moment<2>(args) - mean*mean)/(nr_samples-1); + } + }; + + //! Iterative calculation of the rolling variance. + /*! + Iterative calculation of sample variance \f$\sigma_n^2\f$ is done as follows, see also + http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance. + For a rolling window of size \f$N\f$, for the first \f$N\f$ samples, the variance is computed according to the formula + \f[ + \sigma_n^2 = \frac{1}{n-1} \sum_{i = 1}^n (x_i - \mu_n)^2 = \frac{1}{n-1}M_{2,n}, + \f] + where the sum of squares \f$M_{2,n}\f$ can be recursively computed as: + \f[ + M_{2,n} = \sum_{i = 1}^n (x_i - \mu_n)^2 = M_{2,n-1} + (x_n - \mu_n)(x_n - \mu_{n-1}), + \f] + and the estimate of the sample mean as: + \f[ + \mu_n = \frac{1}{n} \sum_{i = 1}^n x_i = \mu_{n-1} + \frac{1}{n}(x_n - \mu_{n-1}). + \f] + For further samples, when the rolling window is fully filled with data, one has to take into account that the oldest + sample \f$x_{n-N}\f$ is dropped from the window. The sample variance over the window now becomes: + \f[ + \sigma_n^2 = \frac{1}{N-1} \sum_{i = n-N+1}^n (x_i - \mu_n)^2 = \frac{1}{n-1}M_{2,n}, + \f] + where the sum of squares \f$M_{2,n}\f$ now equals: + \f[ + M_{2,n} = \sum_{i = n-N+1}^n (x_i - \mu_n)^2 = M_{2,n-1} + (x_n - \mu_n)(x_n - \mu_{n-1}) - (x_{n-N} - \mu_n)(x_{n-N} - \mu_{n-1}), + \f] + and the estimated mean is: + \f[ + \mu_n = \frac{1}{N} \sum_{i = n-N+1}^n x_i = \mu_{n-1} + \frac{1}{n}(x_n - x_{n-N}). + \f] + + Note that the sample variance is not defined for \f$n <= 1\f$. + + */ + /////////////////////////////////////////////////////////////////////////////// + // immediate_rolling_variance_impl + // + template<typename Sample> + struct immediate_rolling_variance_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + template<typename Args> + immediate_rolling_variance_impl(Args const &args) + : previous_mean_(numeric::fdiv(args[sample | Sample()], numeric::one<std::size_t>::value)) + , sum_of_squares_(numeric::fdiv(args[sample | Sample()], numeric::one<std::size_t>::value)) + { + } + + template<typename Args> + void operator()(Args const &args) + { + Sample added_sample = args[sample]; + + result_type mean = immediate_rolling_mean(args); + sum_of_squares_ += (added_sample-mean)*(added_sample-previous_mean_); + + if(is_rolling_window_plus1_full(args)) + { + Sample removed_sample = rolling_window_plus1(args).front(); + sum_of_squares_ -= (removed_sample-mean)*(removed_sample-previous_mean_); + prevent_underflow(sum_of_squares_); + } + previous_mean_ = mean; + } + + template<typename Args> + result_type result(Args const &args) const + { + size_t nr_samples = rolling_count(args); + if (nr_samples < 2) return result_type(); + return numeric::fdiv(sum_of_squares_,(nr_samples-1)); + } + + private: + + result_type previous_mean_; + result_type sum_of_squares_; + + template<typename T> + void prevent_underflow(T &non_negative_number,typename boost::enable_if<boost::is_arithmetic<T>,T>::type* = 0) + { + if (non_negative_number < T(0)) non_negative_number = T(0); + } + template<typename T> + void prevent_underflow(T &non_arithmetic_quantity,typename boost::disable_if<boost::is_arithmetic<T>,T>::type* = 0) + { + } + }; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag:: lazy_rolling_variance +// tag:: immediate_rolling_variance +// tag:: rolling_variance +// +namespace tag +{ + struct lazy_rolling_variance + : depends_on< rolling_count, rolling_mean, rolling_moment<2> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::lazy_rolling_variance_impl< mpl::_1 > impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword<tag::rolling_window_size> const window_size; + #endif + }; + + struct immediate_rolling_variance + : depends_on< rolling_window_plus1, rolling_count, immediate_rolling_mean> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_rolling_variance_impl< mpl::_1> impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::window_size named parameter + static boost::parameter::keyword<tag::rolling_window_size> const window_size; + #endif + }; + + // make immediate_rolling_variance the default implementation + struct rolling_variance : immediate_rolling_variance {}; +} // namespace tag + +/////////////////////////////////////////////////////////////////////////////// +// extract::lazy_rolling_variance +// extract::immediate_rolling_variance +// extract::rolling_variance +// +namespace extract +{ + extractor<tag::lazy_rolling_variance> const lazy_rolling_variance = {}; + extractor<tag::immediate_rolling_variance> const immediate_rolling_variance = {}; + extractor<tag::rolling_variance> const rolling_variance = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(lazy_rolling_variance) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(immediate_rolling_variance) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_variance) +} + +using extract::lazy_rolling_variance; +using extract::immediate_rolling_variance; +using extract::rolling_variance; + +// rolling_variance(lazy) -> lazy_rolling_variance +template<> +struct as_feature<tag::rolling_variance(lazy)> +{ + typedef tag::lazy_rolling_variance type; +}; + +// rolling_variance(immediate) -> immediate_rolling_variance +template<> +struct as_feature<tag::rolling_variance(immediate)> +{ + typedef tag::immediate_rolling_variance type; +}; + +// for the purposes of feature-based dependency resolution, +// lazy_rolling_variance provides the same feature as rolling_variance +template<> +struct feature_of<tag::lazy_rolling_variance> + : feature_of<tag::rolling_variance> +{ +}; + +// for the purposes of feature-based dependency resolution, +// immediate_rolling_variance provides the same feature as rolling_variance +template<> +struct feature_of<tag::immediate_rolling_variance> + : feature_of<tag::rolling_variance> +{ +}; +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/rolling_window.hpp b/boost/boost/accumulators/statistics/rolling_window.hpp new file mode 100644 index 0000000..2e0a334 --- /dev/null +++ b/boost/boost/accumulators/statistics/rolling_window.hpp
@@ -0,0 +1,172 @@ +/////////////////////////////////////////////////////////////////////////////// +// rolling_window.hpp +// +// Copyright 2008 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_ROLLING_WINDOW_HPP_EAN_26_12_2008 +#define BOOST_ACCUMULATORS_STATISTICS_ROLLING_WINDOW_HPP_EAN_26_12_2008 + +#include <cstddef> +#include <boost/version.hpp> +#include <boost/assert.hpp> +#include <boost/circular_buffer.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/framework/parameters/accumulator.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/statistics_fwd.hpp> + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// tag::rolling_window::size named parameter +BOOST_PARAMETER_NESTED_KEYWORD(tag, rolling_window_size, window_size) + +BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_size) + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // rolling_window_plus1_impl + // stores the latest N+1 samples, where N is specified at construction time + // with the rolling_window_size named parameter + template<typename Sample> + struct rolling_window_plus1_impl + : accumulator_base + { + typedef typename circular_buffer<Sample>::const_iterator const_iterator; + typedef iterator_range<const_iterator> result_type; + + template<typename Args> + rolling_window_plus1_impl(Args const & args) + : buffer_(args[rolling_window_size] + 1) + {} + + #if BOOST_VERSION < 103600 + // Before Boost 1.36, copying a circular buffer didn't copy + // it's capacity, and we need that behavior. + rolling_window_plus1_impl(rolling_window_plus1_impl const &that) + : buffer_(that.buffer_) + { + this->buffer_.set_capacity(that.buffer_.capacity()); + } + + rolling_window_plus1_impl &operator =(rolling_window_plus1_impl const &that) + { + this->buffer_ = that.buffer_; + this->buffer_.set_capacity(that.buffer_.capacity()); + } + #endif + + template<typename Args> + void operator ()(Args const &args) + { + this->buffer_.push_back(args[sample]); + } + + bool full() const + { + return this->buffer_.full(); + } + + // The result of a shifted rolling window is the range including + // everything except the most recently added element. + result_type result(dont_care) const + { + return result_type(this->buffer_.begin(), this->buffer_.end()); + } + + private: + circular_buffer<Sample> buffer_; + }; + + template<typename Args> + bool is_rolling_window_plus1_full(Args const &args) + { + return find_accumulator<tag::rolling_window_plus1>(args[accumulator]).full(); + } + + /////////////////////////////////////////////////////////////////////////////// + // rolling_window_impl + // stores the latest N samples, where N is specified at construction type + // with the rolling_window_size named parameter + template<typename Sample> + struct rolling_window_impl + : accumulator_base + { + typedef typename circular_buffer<Sample>::const_iterator const_iterator; + typedef iterator_range<const_iterator> result_type; + + rolling_window_impl(dont_care) + {} + + template<typename Args> + result_type result(Args const &args) const + { + return rolling_window_plus1(args).advance_begin(is_rolling_window_plus1_full(args)); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::rolling_window_plus1 +// tag::rolling_window +// +namespace tag +{ + struct rolling_window_plus1 + : depends_on<> + , tag::rolling_window_size + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::rolling_window_plus1_impl< mpl::_1 > impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::size named parameter + static boost::parameter::keyword<tag::rolling_window_size> const window_size; + #endif + }; + + struct rolling_window + : depends_on< rolling_window_plus1 > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::rolling_window_impl< mpl::_1 > impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::rolling_window::size named parameter + static boost::parameter::keyword<tag::rolling_window_size> const window_size; + #endif + }; + +} // namespace tag + +/////////////////////////////////////////////////////////////////////////////// +// extract::rolling_window_plus1 +// extract::rolling_window +// +namespace extract +{ + extractor<tag::rolling_window_plus1> const rolling_window_plus1 = {}; + extractor<tag::rolling_window> const rolling_window = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window_plus1) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(rolling_window) +} + +using extract::rolling_window_plus1; +using extract::rolling_window; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/skewness.hpp b/boost/boost/accumulators/statistics/skewness.hpp new file mode 100644 index 0000000..c383ec4 --- /dev/null +++ b/boost/boost/accumulators/statistics/skewness.hpp
@@ -0,0 +1,114 @@ +/////////////////////////////////////////////////////////////////////////////// +// skewness.hpp +// +// Copyright 2006 Olivier Gygi, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_SKEWNESS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_SKEWNESS_HPP_EAN_28_10_2005 + +#include <limits> +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/moment.hpp> +#include <boost/accumulators/statistics/mean.hpp> + + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // skewness_impl + /** + @brief Skewness estimation + + The skewness of a sample distribution is defined as the ratio of the 3rd central moment and the \f$ 3/2 \f$-th power + of the 2nd central moment (the variance) of the samples 3. The skewness can also be expressed by the simple moments: + + \f[ + \hat{g}_1 = + \frac + {\widehat{m}_n^{(3)}-3\widehat{m}_n^{(2)}\hat{\mu}_n+2\hat{\mu}_n^3} + {\left(\widehat{m}_n^{(2)} - \hat{\mu}_n^{2}\right)^{3/2}} + \f] + + where \f$ \widehat{m}_n^{(i)} \f$ are the \f$ i \f$-th moment and \f$ \hat{\mu}_n \f$ the mean (first moment) of the + \f$ n \f$ samples. + */ + template<typename Sample> + struct skewness_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, Sample>::result_type result_type; + + skewness_impl(dont_care) + { + } + + template<typename Args> + result_type result(Args const &args) const + { + return numeric::fdiv( + accumulators::moment<3>(args) + - 3. * accumulators::moment<2>(args) * mean(args) + + 2. * mean(args) * mean(args) * mean(args) + , ( accumulators::moment<2>(args) - mean(args) * mean(args) ) + * std::sqrt( accumulators::moment<2>(args) - mean(args) * mean(args) ) + ); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::skewness +// +namespace tag +{ + struct skewness + : depends_on<mean, moment<2>, moment<3> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::skewness_impl<mpl::_1> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::skewness +// +namespace extract +{ + extractor<tag::skewness> const skewness = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(skewness) +} + +using extract::skewness; + +// So that skewness can be automatically substituted with +// weighted_skewness when the weight parameter is non-void +template<> +struct as_weighted_feature<tag::skewness> +{ + typedef tag::weighted_skewness type; +}; + +template<> +struct feature_of<tag::weighted_skewness> + : feature_of<tag::skewness> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/stats.hpp b/boost/boost/accumulators/statistics/stats.hpp new file mode 100644 index 0000000..22c4ede --- /dev/null +++ b/boost/boost/accumulators/statistics/stats.hpp
@@ -0,0 +1,29 @@ +/////////////////////////////////////////////////////////////////////////////// +/// \file stats.hpp +/// Contains the stats<> template. +/// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_STATS_HPP_EAN_28_10_2005 + +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/accumulators/statistics_fwd.hpp> + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +/// An MPL sequence of statistics. +template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Stat)> +struct stats + : mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Stat)> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/sum.hpp b/boost/boost/accumulators/statistics/sum.hpp new file mode 100644 index 0000000..126ce24 --- /dev/null +++ b/boost/boost/accumulators/statistics/sum.hpp
@@ -0,0 +1,141 @@ +/////////////////////////////////////////////////////////////////////////////// +// sum.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_SUM_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_SUM_HPP_EAN_28_10_2005 + +#include <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/framework/parameters/weight.hpp> +#include <boost/accumulators/framework/accumulators/external_accumulator.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // sum_impl + template<typename Sample, typename Tag> + struct sum_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + template<typename Args> + sum_impl(Args const &args) + : sum(args[parameter::keyword<Tag>::get() | Sample()]) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + // what about overflow? + this->sum += args[parameter::keyword<Tag>::get()]; + } + + result_type result(dont_care) const + { + return this->sum; + } + + private: + + Sample sum; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::sum +// tag::sum_of_weights +// tag::sum_of_variates +// +namespace tag +{ + struct sum + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::sum_impl<mpl::_1, tag::sample> impl; + }; + + struct sum_of_weights + : depends_on<> + { + typedef mpl::true_ is_weight_accumulator; + /// INTERNAL ONLY + /// + typedef accumulators::impl::sum_impl<mpl::_2, tag::weight> impl; + }; + + template<typename VariateType, typename VariateTag> + struct sum_of_variates + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef mpl::always<accumulators::impl::sum_impl<VariateType, VariateTag> > impl; + }; + + struct abstract_sum_of_variates + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::sum +// extract::sum_of_weights +// extract::sum_of_variates +// +namespace extract +{ + extractor<tag::sum> const sum = {}; + extractor<tag::sum_of_weights> const sum_of_weights = {}; + extractor<tag::abstract_sum_of_variates> const sum_of_variates = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_of_weights) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_of_variates) +} + +using extract::sum; +using extract::sum_of_weights; +using extract::sum_of_variates; + +// So that mean can be automatically substituted with +// weighted_mean when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::sum> +{ + typedef tag::weighted_sum type; +}; + +template<> +struct feature_of<tag::weighted_sum> + : feature_of<tag::sum> +{}; + +template<typename VariateType, typename VariateTag> +struct feature_of<tag::sum_of_variates<VariateType, VariateTag> > + : feature_of<tag::abstract_sum_of_variates> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/sum_kahan.hpp b/boost/boost/accumulators/statistics/sum_kahan.hpp new file mode 100644 index 0000000..97ade18 --- /dev/null +++ b/boost/boost/accumulators/statistics/sum_kahan.hpp
@@ -0,0 +1,188 @@ +/////////////////////////////////////////////////////////////////////////////// +// sum_kahan.hpp +// +// Copyright 2010 Gaetano Mendola, 2011 Simon West. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_SUM_KAHAN_HPP_EAN_26_07_2010 +#define BOOST_ACCUMULATORS_STATISTICS_SUM_KAHAN_HPP_EAN_26_07_2010 + +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/sum.hpp> +#include <boost/accumulators/statistics/weighted_sum_kahan.hpp> +#include <boost/numeric/conversion/cast.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + +#if _MSC_VER > 1400 +# pragma float_control(push) +# pragma float_control(precise, on) +#endif + +template<typename Sample, typename Tag> +struct sum_kahan_impl + : accumulator_base +{ + typedef Sample result_type; + + //////////////////////////////////////////////////////////////////////////// + // sum_kahan_impl + /** + @brief Kahan summation algorithm + + The Kahan summation algorithm reduces the numerical error obtained with standard + sequential sum. + + */ + template<typename Args> + sum_kahan_impl(Args const & args) + : sum(args[parameter::keyword<Tag>::get() | Sample()]), + compensation(boost::numeric_cast<Sample>(0.0)) + { + } + + template<typename Args> + void +#if BOOST_ACCUMULATORS_GCC_VERSION > 40305 + __attribute__((__optimize__("no-associative-math"))) +#endif + operator ()(Args const & args) + { + const Sample myTmp1 = args[parameter::keyword<Tag>::get()] - this->compensation; + const Sample myTmp2 = this->sum + myTmp1; + this->compensation = (myTmp2 - this->sum) - myTmp1; + this->sum = myTmp2; + } + + result_type result(dont_care) const + { + return this->sum; + } + +private: + Sample sum; + Sample compensation; +}; + +#if _MSC_VER > 1400 +# pragma float_control(pop) +#endif + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::sum_kahan +// tag::sum_of_weights_kahan +// tag::sum_of_variates_kahan +// +namespace tag +{ + + struct sum_kahan + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef impl::sum_kahan_impl< mpl::_1, tag::sample > impl; + }; + + struct sum_of_weights_kahan + : depends_on<> + { + typedef mpl::true_ is_weight_accumulator; + /// INTERNAL ONLY + /// + typedef accumulators::impl::sum_kahan_impl<mpl::_2, tag::weight> impl; + }; + + template<typename VariateType, typename VariateTag> + struct sum_of_variates_kahan + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef mpl::always<accumulators::impl::sum_kahan_impl<VariateType, VariateTag> > impl; + }; + +} // namespace tag + +/////////////////////////////////////////////////////////////////////////////// +// extract::sum_kahan +// extract::sum_of_weights_kahan +// extract::sum_of_variates_kahan +// +namespace extract +{ + extractor<tag::sum_kahan> const sum_kahan = {}; + extractor<tag::sum_of_weights_kahan> const sum_of_weights_kahan = {}; + extractor<tag::abstract_sum_of_variates> const sum_of_variates_kahan = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_kahan) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_of_weights_kahan) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(sum_of_variates_kahan) +} // namespace extract + +using extract::sum_kahan; +using extract::sum_of_weights_kahan; +using extract::sum_of_variates_kahan; + +// sum(kahan) -> sum_kahan +template<> +struct as_feature<tag::sum(kahan)> +{ + typedef tag::sum_kahan type; +}; + +// sum_of_weights(kahan) -> sum_of_weights_kahan +template<> +struct as_feature<tag::sum_of_weights(kahan)> +{ + typedef tag::sum_of_weights_kahan type; +}; + +// So that sum_kahan can be automatically substituted with +// weighted_sum_kahan when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::sum_kahan> +{ + typedef tag::weighted_sum_kahan type; +}; + +template<> +struct feature_of<tag::weighted_sum_kahan> + : feature_of<tag::sum> +{}; + +// for the purposes of feature-based dependency resolution, +// sum_kahan provides the same feature as sum +template<> +struct feature_of<tag::sum_kahan> + : feature_of<tag::sum> +{ +}; + +// for the purposes of feature-based dependency resolution, +// sum_of_weights_kahan provides the same feature as sum_of_weights +template<> +struct feature_of<tag::sum_of_weights_kahan> + : feature_of<tag::sum_of_weights> +{ +}; + +template<typename VariateType, typename VariateTag> +struct feature_of<tag::sum_of_variates_kahan<VariateType, VariateTag> > + : feature_of<tag::abstract_sum_of_variates> +{ +}; + +}} // namespace boost::accumulators + +#endif +
diff --git a/boost/boost/accumulators/statistics/tail.hpp b/boost/boost/accumulators/statistics/tail.hpp new file mode 100644 index 0000000..cc9267f --- /dev/null +++ b/boost/boost/accumulators/statistics/tail.hpp
@@ -0,0 +1,338 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail.hpp +// +// Copyright 2005 Eric Niebler, Michael Gauckler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_TAIL_HPP_EAN_28_10_2005 + +#include <vector> +#include <functional> +#include <boost/assert.hpp> +#include <boost/range.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/or.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/iterator/reverse_iterator.hpp> +#include <boost/iterator/permutation_iterator.hpp> +#include <boost/accumulators/accumulators_fwd.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> + +namespace boost { namespace accumulators +{ +/////////////////////////////////////////////////////////////////////////////// +// cache_size named parameters +BOOST_PARAMETER_NESTED_KEYWORD(tag, right_tail_cache_size, cache_size) +BOOST_PARAMETER_NESTED_KEYWORD(tag, left_tail_cache_size, cache_size) + +BOOST_ACCUMULATORS_IGNORE_GLOBAL(right_tail_cache_size) +BOOST_ACCUMULATORS_IGNORE_GLOBAL(left_tail_cache_size) + +namespace detail +{ + /////////////////////////////////////////////////////////////////////////////// + // tail_range + /// INTERNAL ONLY + /// + template<typename ElementIterator, typename IndexIterator> + struct tail_range + { + typedef boost::iterator_range< + boost::reverse_iterator<boost::permutation_iterator<ElementIterator, IndexIterator> > + > type; + }; + + /////////////////////////////////////////////////////////////////////////////// + // make_tail_range + /// INTERNAL ONLY + /// + template<typename ElementIterator, typename IndexIterator> + typename tail_range<ElementIterator, IndexIterator>::type + make_tail_range(ElementIterator elem_begin, IndexIterator index_begin, IndexIterator index_end) + { + return boost::make_iterator_range( + boost::make_reverse_iterator( + boost::make_permutation_iterator(elem_begin, index_end) + ) + , boost::make_reverse_iterator( + boost::make_permutation_iterator(elem_begin, index_begin) + ) + ); + } + + /////////////////////////////////////////////////////////////////////////////// + // stat_assign_visitor + /// INTERNAL ONLY + /// + template<typename Args> + struct stat_assign_visitor + { + stat_assign_visitor(Args const &a, std::size_t i) + : args(a) + , index(i) + { + } + + template<typename Stat> + void operator ()(Stat &stat) const + { + stat.assign(this->args, this->index); + } + + private: + stat_assign_visitor &operator =(stat_assign_visitor const &); + Args const &args; + std::size_t index; + }; + + /////////////////////////////////////////////////////////////////////////////// + // stat_assign + /// INTERNAL ONLY + /// + template<typename Args> + inline stat_assign_visitor<Args> const stat_assign(Args const &args, std::size_t index) + { + return stat_assign_visitor<Args>(args, index); + } + + /////////////////////////////////////////////////////////////////////////////// + // is_tail_variate_feature + /// INTERNAL ONLY + /// + template<typename Stat, typename LeftRight> + struct is_tail_variate_feature + : mpl::false_ + { + }; + + /// INTERNAL ONLY + /// + template<typename VariateType, typename VariateTag, typename LeftRight> + struct is_tail_variate_feature<tag::tail_variate<VariateType, VariateTag, LeftRight>, LeftRight> + : mpl::true_ + { + }; + + /// INTERNAL ONLY + /// + template<typename LeftRight> + struct is_tail_variate_feature<tag::tail_weights<LeftRight>, LeftRight> + : mpl::true_ + { + }; + +} // namespace detail + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // tail_impl + template<typename Sample, typename LeftRight> + struct tail_impl + : accumulator_base + { + // LeftRight must be either right or left + BOOST_MPL_ASSERT(( + mpl::or_<is_same<LeftRight, right>, is_same<LeftRight, left> > + )); + + typedef + typename mpl::if_< + is_same<LeftRight, right> + , numeric::functional::greater<Sample const, Sample const> + , numeric::functional::less<Sample const, Sample const> + >::type + predicate_type; + + // for boost::result_of + typedef typename detail::tail_range< + typename std::vector<Sample>::const_iterator + , std::vector<std::size_t>::iterator + >::type result_type; + + template<typename Args> + tail_impl(Args const &args) + : is_sorted(false) + , indices() + , samples(args[tag::tail<LeftRight>::cache_size], args[sample | Sample()]) + { + this->indices.reserve(this->samples.size()); + } + + tail_impl(tail_impl const &that) + : is_sorted(that.is_sorted) + , indices(that.indices) + , samples(that.samples) + { + this->indices.reserve(this->samples.size()); + } + + // This just stores the heap and the samples. + // In operator()() below, if we are adding a new sample + // to the sample cache, we force all the + // tail_variates to update also. (It's not + // good enough to wait for the accumulator_set to do it + // for us because then information about whether a sample + // was stored and where is lost, and would need to be + // queried at runtime, which would be slow.) This is + // implemented as a filtered visitation over the stats, + // which we can access because args[accumulator] gives us + // all the stats. + + template<typename Args> + void operator ()(Args const &args) + { + if(this->indices.size() < this->samples.size()) + { + this->indices.push_back(this->indices.size()); + this->assign(args, this->indices.back()); + } + else if(predicate_type()(args[sample], this->samples[this->indices[0]])) + { + std::pop_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples)); + this->assign(args, this->indices.back()); + } + } + + result_type result(dont_care) const + { + if(!this->is_sorted) + { + // Must use the same predicate here as in push_heap/pop_heap above. + std::sort_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples)); + // sort_heap puts elements in reverse order. Calling std::reverse + // turns the sorted sequence back into a valid heap. + std::reverse(this->indices.begin(), this->indices.end()); + this->is_sorted = true; + } + + return detail::make_tail_range( + this->samples.begin() + , this->indices.begin() + , this->indices.end() + ); + } + + private: + + struct is_tail_variate + { + template<typename T> + struct apply + : detail::is_tail_variate_feature< + typename detail::feature_tag<T>::type + , LeftRight + > + {}; + }; + + template<typename Args> + void assign(Args const &args, std::size_t index) + { + BOOST_ASSERT(index < this->samples.size()); + this->samples[index] = args[sample]; + std::push_heap(this->indices.begin(), this->indices.end(), indirect_cmp(this->samples)); + this->is_sorted = false; + // Tell the tail variates to store their values also + args[accumulator].template visit_if<is_tail_variate>(detail::stat_assign(args, index)); + } + + /////////////////////////////////////////////////////////////////////////////// + // + struct indirect_cmp + : std::binary_function<std::size_t, std::size_t, bool> + { + indirect_cmp(std::vector<Sample> const &s) + : samples(s) + { + } + + bool operator ()(std::size_t left, std::size_t right) const + { + return predicate_type()(this->samples[left], this->samples[right]); + } + + private: + indirect_cmp &operator =(indirect_cmp const &); + std::vector<Sample> const &samples; + }; + + mutable bool is_sorted; + mutable std::vector<std::size_t> indices; + std::vector<Sample> samples; + }; + +} // namespace impl + +// TODO The templatized tag::tail below should inherit from the correct named parameter. +// The following lines provide a workaround, but there must be a better way of doing this. +template<typename T> +struct tail_cache_size_named_arg +{ +}; +template<> +struct tail_cache_size_named_arg<left> + : tag::left_tail_cache_size +{ +}; +template<> +struct tail_cache_size_named_arg<right> + : tag::right_tail_cache_size +{ +}; + +/////////////////////////////////////////////////////////////////////////////// +// tag::tail<> +// +namespace tag +{ + template<typename LeftRight> + struct tail + : depends_on<> + , tail_cache_size_named_arg<LeftRight> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::tail_impl<mpl::_1, LeftRight> impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + /// tag::tail<LeftRight>::cache_size named parameter + static boost::parameter::keyword<tail_cache_size_named_arg<LeftRight> > const cache_size; + #endif + }; + + struct abstract_tail + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::tail +// +namespace extract +{ + extractor<tag::abstract_tail> const tail = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(tail) +} + +using extract::tail; + +template<typename LeftRight> +struct feature_of<tag::tail<LeftRight> > + : feature_of<tag::abstract_tail> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/tail_mean.hpp b/boost/boost/accumulators/statistics/tail_mean.hpp new file mode 100644 index 0000000..67dae37 --- /dev/null +++ b/boost/boost/accumulators/statistics/tail_mean.hpp
@@ -0,0 +1,246 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail_mean.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_MEAN_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_TAIL_MEAN_HPP_DE_01_01_2006 + +#include <numeric> +#include <vector> +#include <limits> +#include <functional> +#include <sstream> +#include <stdexcept> +#include <boost/throw_exception.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/type_traits/is_same.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/tail.hpp> +#include <boost/accumulators/statistics/tail_quantile.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + /////////////////////////////////////////////////////////////////////////////// + // coherent_tail_mean_impl + // + /** + @brief Estimation of the coherent tail mean based on order statistics (for both left and right tails) + + The coherent tail mean \f$\widehat{CTM}_{n,\alpha}(X)\f$ is equal to the non-coherent tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$ + plus a correction term that ensures coherence in case of non-continuous distributions. + + \f[ + \widehat{CTM}_{n,\alpha}^{\mathrm{right}}(X) = \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X) + + \frac{1}{\lceil n(1-\alpha)\rceil}\hat{q}_{n,\alpha}(X)\left(1 - \alpha - \frac{1}{n}\lceil n(1-\alpha)\rceil \right) + \f] + + \f[ + \widehat{CTM}_{n,\alpha}^{\mathrm{left}}(X) = \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X) + + \frac{1}{\lceil n\alpha\rceil}\hat{q}_{n,\alpha}(X)\left(\alpha - \frac{1}{n}\lceil n\alpha\rceil \right) + \f] + */ + template<typename Sample, typename LeftRight> + struct coherent_tail_mean_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + // for boost::result_of + typedef float_type result_type; + + coherent_tail_mean_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + std::size_t cnt = count(args); + + std::size_t n = static_cast<std::size_t>( + std::ceil( + cnt * ( ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ) + ) + ); + + extractor<tag::non_coherent_tail_mean<LeftRight> > const some_non_coherent_tail_mean = {}; + + return some_non_coherent_tail_mean(args) + + numeric::fdiv(quantile(args), n) + * ( + ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] + - numeric::fdiv(n, count(args)) + ); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // non_coherent_tail_mean_impl + // + /** + @brief Estimation of the (non-coherent) tail mean based on order statistics (for both left and right tails) + + An estimation of the non-coherent tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$ is given by the mean of the + \f$\lceil n\alpha\rceil\f$ smallest samples (left tail) or the mean of the \f$\lceil n(1-\alpha)\rceil\f$ + largest samples (right tail), \f$n\f$ being the total number of samples and \f$\alpha\f$ the quantile level: + + \f[ + \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X) = \frac{1}{\lceil n(1-\alpha)\rceil} \sum_{i=\lceil \alpha n \rceil}^n X_{i:n} + \f] + + \f[ + \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X) = \frac{1}{\lceil n\alpha\rceil} \sum_{i=1}^{\lceil \alpha n \rceil} X_{i:n} + \f] + + It thus requires the caching of at least the \f$\lceil n\alpha\rceil\f$ smallest or the \f$\lceil n(1-\alpha)\rceil\f$ + largest samples. + + @param quantile_probability + */ + template<typename Sample, typename LeftRight> + struct non_coherent_tail_mean_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + // for boost::result_of + typedef float_type result_type; + + non_coherent_tail_mean_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + std::size_t cnt = count(args); + + std::size_t n = static_cast<std::size_t>( + std::ceil( + cnt * ( ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ) + ) + ); + + // If n is in a valid range, return result, otherwise return NaN or throw exception + if (n <= static_cast<std::size_t>(tail(args).size())) + return numeric::fdiv( + std::accumulate( + tail(args).begin() + , tail(args).begin() + n + , Sample(0) + ) + , n + ); + else + { + if (std::numeric_limits<result_type>::has_quiet_NaN) + { + return std::numeric_limits<result_type>::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return Sample(0); + } + } + } + }; + +} // namespace impl + + +/////////////////////////////////////////////////////////////////////////////// +// tag::coherent_tail_mean<> +// tag::non_coherent_tail_mean<> +// +namespace tag +{ + template<typename LeftRight> + struct coherent_tail_mean + : depends_on<count, quantile, non_coherent_tail_mean<LeftRight> > + { + typedef accumulators::impl::coherent_tail_mean_impl<mpl::_1, LeftRight> impl; + }; + + template<typename LeftRight> + struct non_coherent_tail_mean + : depends_on<count, tail<LeftRight> > + { + typedef accumulators::impl::non_coherent_tail_mean_impl<mpl::_1, LeftRight> impl; + }; + + struct abstract_non_coherent_tail_mean + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::non_coherent_tail_mean; +// extract::coherent_tail_mean; +// +namespace extract +{ + extractor<tag::abstract_non_coherent_tail_mean> const non_coherent_tail_mean = {}; + extractor<tag::tail_mean> const coherent_tail_mean = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(non_coherent_tail_mean) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(coherent_tail_mean) +} + +using extract::non_coherent_tail_mean; +using extract::coherent_tail_mean; + +// for the purposes of feature-based dependency resolution, +// coherent_tail_mean<LeftRight> provides the same feature as tail_mean +template<typename LeftRight> +struct feature_of<tag::coherent_tail_mean<LeftRight> > + : feature_of<tag::tail_mean> +{ +}; + +template<typename LeftRight> +struct feature_of<tag::non_coherent_tail_mean<LeftRight> > + : feature_of<tag::abstract_non_coherent_tail_mean> +{ +}; + +// So that non_coherent_tail_mean can be automatically substituted +// with weighted_non_coherent_tail_mean when the weight parameter is non-void. +template<typename LeftRight> +struct as_weighted_feature<tag::non_coherent_tail_mean<LeftRight> > +{ + typedef tag::non_coherent_weighted_tail_mean<LeftRight> type; +}; + +template<typename LeftRight> +struct feature_of<tag::non_coherent_weighted_tail_mean<LeftRight> > + : feature_of<tag::non_coherent_tail_mean<LeftRight> > +{}; + +// NOTE that non_coherent_tail_mean cannot be feature-grouped with tail_mean, +// which is the base feature for coherent tail means, since (at least for +// non-continuous distributions) non_coherent_tail_mean is a different measure! + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif
diff --git a/boost/boost/accumulators/statistics/tail_quantile.hpp b/boost/boost/accumulators/statistics/tail_quantile.hpp new file mode 100644 index 0000000..9ff56b5 --- /dev/null +++ b/boost/boost/accumulators/statistics/tail_quantile.hpp
@@ -0,0 +1,158 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail_quantile.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_TAIL_QUANTILE_HPP_DE_01_01_2006 + +#include <vector> +#include <limits> +#include <functional> +#include <sstream> +#include <stdexcept> +#include <boost/config/no_tr1/cmath.hpp> // For ceil +#include <boost/throw_exception.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/mpl/if.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/accumulators/framework/depends_on.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/tail.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // tail_quantile_impl + // Tail quantile estimation based on order statistics + /** + @brief Tail quantile estimation based on order statistics (for both left and right tails) + + The estimation of a tail quantile \f$\hat{q}\f$ with level \f$\alpha\f$ based on order statistics requires the + caching of at least the \f$\lceil n\alpha\rceil\f$ smallest or the \f$\lceil n(1-\alpha)\rceil\f$ largest samples, + \f$n\f$ being the total number of samples. The largest of the \f$\lceil n\alpha\rceil\f$ smallest samples or the + smallest of the \f$\lceil n(1-\alpha)\rceil\f$ largest samples provides an estimate for the quantile: + + \f[ + \hat{q}_{n,\alpha} = X_{\lceil \alpha n \rceil:n} + \f] + + @param quantile_probability + */ + template<typename Sample, typename LeftRight> + struct tail_quantile_impl + : accumulator_base + { + // for boost::result_of + typedef Sample result_type; + + tail_quantile_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + std::size_t cnt = count(args); + + std::size_t n = static_cast<std::size_t>( + std::ceil( + cnt * ( ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ) + ) + ); + + // If n is in a valid range, return result, otherwise return NaN or throw exception + if ( n < static_cast<std::size_t>(tail(args).size())) + { + // Note that the cached samples of the left are sorted in ascending order, + // whereas the samples of the right tail are sorted in descending order + return *(boost::begin(tail(args)) + n - 1); + } + else + { + if (std::numeric_limits<result_type>::has_quiet_NaN) + { + return std::numeric_limits<result_type>::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return Sample(0); + } + } + } + }; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::tail_quantile<> +// +namespace tag +{ + template<typename LeftRight> + struct tail_quantile + : depends_on<count, tail<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::tail_quantile_impl<mpl::_1, LeftRight> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::tail_quantile +// +namespace extract +{ + extractor<tag::quantile> const tail_quantile = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(tail_quantile) +} + +using extract::tail_quantile; + +// for the purposes of feature-based dependency resolution, +// tail_quantile<LeftRight> provide the same feature as quantile +template<typename LeftRight> +struct feature_of<tag::tail_quantile<LeftRight> > + : feature_of<tag::quantile> +{ +}; + +// So that tail_quantile can be automatically substituted with +// weighted_tail_quantile when the weight parameter is non-void. +template<typename LeftRight> +struct as_weighted_feature<tag::tail_quantile<LeftRight> > +{ + typedef tag::weighted_tail_quantile<LeftRight> type; +}; + +template<typename LeftRight> +struct feature_of<tag::weighted_tail_quantile<LeftRight> > + : feature_of<tag::tail_quantile<LeftRight> > +{}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif
diff --git a/boost/boost/accumulators/statistics/tail_variate.hpp b/boost/boost/accumulators/statistics/tail_variate.hpp new file mode 100644 index 0000000..a9fc7d2 --- /dev/null +++ b/boost/boost/accumulators/statistics/tail_variate.hpp
@@ -0,0 +1,141 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail_variate.hpp +// +// Copyright 2005 Eric Niebler, Michael Gauckler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STAT_STATISTICS_TAIL_VARIATE_HPP_EAN_28_10_2005 +#define BOOST_STAT_STATISTICS_TAIL_VARIATE_HPP_EAN_28_10_2005 + +#include <boost/range.hpp> +#include <boost/mpl/always.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/iterator/reverse_iterator.hpp> +#include <boost/iterator/permutation_iterator.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/tail.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // tail_variate_impl + template<typename VariateType, typename VariateTag, typename LeftRight> + struct tail_variate_impl + : accumulator_base + { + // for boost::result_of + typedef + typename detail::tail_range< + typename std::vector<VariateType>::const_iterator + , std::vector<std::size_t>::iterator + >::type + result_type; + + template<typename Args> + tail_variate_impl(Args const &args) + : variates(args[tag::tail<LeftRight>::cache_size], args[parameter::keyword<VariateTag>::get() | VariateType()]) + { + } + + template<typename Args> + void assign(Args const &args, std::size_t index) + { + this->variates[index] = args[parameter::keyword<VariateTag>::get()]; + } + + template<typename Args> + result_type result(Args const &args) const + { + // getting the order result causes the indices vector to be sorted. + extractor<tag::tail<LeftRight> > const some_tail = {}; + return this->do_result(some_tail(args)); + } + + private: + template<typename TailRng> + result_type do_result(TailRng const &rng) const + { + return detail::make_tail_range( + this->variates.begin() + , rng.end().base().base() // the index iterator + , rng.begin().base().base() // (begin and end reversed because these are reverse iterators) + ); + } + + std::vector<VariateType> variates; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::tail_variate<> +// +namespace tag +{ + template<typename VariateType, typename VariateTag, typename LeftRight> + struct tail_variate + : depends_on<tail<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef mpl::always<accumulators::impl::tail_variate_impl<VariateType, VariateTag, LeftRight> > impl; + }; + + struct abstract_tail_variate + : depends_on<> + { + }; + + template<typename LeftRight> + struct tail_weights + : depends_on<tail<LeftRight> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::tail_variate_impl<mpl::_2, tag::weight, LeftRight> impl; + }; + + struct abstract_tail_weights + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::tail_variate +// extract::tail_weights +// +namespace extract +{ + extractor<tag::abstract_tail_variate> const tail_variate = {}; + extractor<tag::abstract_tail_weights> const tail_weights = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(tail_variate) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(tail_weights) +} + +using extract::tail_variate; +using extract::tail_weights; + +template<typename VariateType, typename VariateTag, typename LeftRight> +struct feature_of<tag::tail_variate<VariateType, VariateTag, LeftRight> > + : feature_of<tag::abstract_tail_variate> +{ +}; + +template<typename LeftRight> +struct feature_of<tag::tail_weights<LeftRight> > +{ + typedef tag::abstract_tail_weights type; +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/tail_variate_means.hpp b/boost/boost/accumulators/statistics/tail_variate_means.hpp new file mode 100644 index 0000000..d34d4ab --- /dev/null +++ b/boost/boost/accumulators/statistics/tail_variate_means.hpp
@@ -0,0 +1,258 @@ +/////////////////////////////////////////////////////////////////////////////// +// tail_variate_means.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 + +#include <numeric> +#include <vector> +#include <limits> +#include <functional> +#include <sstream> +#include <stdexcept> +#include <boost/throw_exception.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/type_traits/is_same.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/tail.hpp> +#include <boost/accumulators/statistics/tail_variate.hpp> +#include <boost/accumulators/statistics/tail_mean.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /** + @brief Estimation of the absolute and relative tail variate means (for both left and right tails) + + For all \f$j\f$-th variates associated to the \f$\lceil n(1-\alpha)\rceil\f$ largest samples (or the + \f$\lceil n(1-\alpha)\rceil\f$ smallest samples in case of the left tail), the absolute tail means + \f$\widehat{ATM}_{n,\alpha}(X, j)\f$ are computed and returned as an iterator range. Alternatively, + the relative tail means \f$\widehat{RTM}_{n,\alpha}(X, j)\f$ are returned, which are the absolute + tail means normalized with the (non-coherent) sample tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$. + + \f[ + \widehat{ATM}_{n,\alpha}^{\mathrm{right}}(X, j) = + \frac{1}{\lceil n(1-\alpha) \rceil} + \sum_{i=\lceil \alpha n \rceil}^n \xi_{j,i} + \f] + + \f[ + \widehat{ATM}_{n,\alpha}^{\mathrm{left}}(X, j) = + \frac{1}{\lceil n\alpha \rceil} + \sum_{i=1}^{\lceil n\alpha \rceil} \xi_{j,i} + \f] + + \f[ + \widehat{RTM}_{n,\alpha}^{\mathrm{right}}(X, j) = + \frac{\sum_{i=\lceil n\alpha \rceil}^n \xi_{j,i}} + {\lceil n(1-\alpha)\rceil\widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X)} + \f] + + \f[ + \widehat{RTM}_{n,\alpha}^{\mathrm{left}}(X, j) = + \frac{\sum_{i=1}^{\lceil n\alpha \rceil} \xi_{j,i}} + {\lceil n\alpha\rceil\widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X)} + \f] + */ + + /////////////////////////////////////////////////////////////////////////////// + // tail_variate_means_impl + // by default: absolute tail_variate_means + template<typename Sample, typename Impl, typename LeftRight, typename VariateTag> + struct tail_variate_means_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + typedef std::vector<float_type> array_type; + // for boost::result_of + typedef iterator_range<typename array_type::iterator> result_type; + + tail_variate_means_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + std::size_t cnt = count(args); + + std::size_t n = static_cast<std::size_t>( + std::ceil( + cnt * ( ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ) + ) + ); + + std::size_t num_variates = tail_variate(args).begin()->size(); + + this->tail_means_.clear(); + this->tail_means_.resize(num_variates, Sample(0)); + + // If n is in a valid range, return result, otherwise return NaN or throw exception + if (n < static_cast<std::size_t>(tail(args).size())) + { + this->tail_means_ = std::accumulate( + tail_variate(args).begin() + , tail_variate(args).begin() + n + , this->tail_means_ + , numeric::plus + ); + + float_type factor = n * ( (is_same<Impl, relative>::value) ? non_coherent_tail_mean(args) : 1. ); + + std::transform( + this->tail_means_.begin() + , this->tail_means_.end() + , this->tail_means_.begin() + , std::bind2nd(std::divides<float_type>(), factor) + ); + } + else + { + if (std::numeric_limits<float_type>::has_quiet_NaN) + { + std::fill( + this->tail_means_.begin() + , this->tail_means_.end() + , std::numeric_limits<float_type>::quiet_NaN() + ); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + } + } + return make_iterator_range(this->tail_means_); + } + + private: + + mutable array_type tail_means_; + + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::absolute_tail_variate_means +// tag::relative_tail_variate_means +// +namespace tag +{ + template<typename LeftRight, typename VariateType, typename VariateTag> + struct absolute_tail_variate_means + : depends_on<count, non_coherent_tail_mean<LeftRight>, tail_variate<VariateType, VariateTag, LeftRight> > + { + typedef accumulators::impl::tail_variate_means_impl<mpl::_1, absolute, LeftRight, VariateTag> impl; + }; + template<typename LeftRight, typename VariateType, typename VariateTag> + struct relative_tail_variate_means + : depends_on<count, non_coherent_tail_mean<LeftRight>, tail_variate<VariateType, VariateTag, LeftRight> > + { + typedef accumulators::impl::tail_variate_means_impl<mpl::_1, relative, LeftRight, VariateTag> impl; + }; + struct abstract_absolute_tail_variate_means + : depends_on<> + { + }; + struct abstract_relative_tail_variate_means + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::tail_variate_means +// extract::relative_tail_variate_means +// +namespace extract +{ + extractor<tag::abstract_absolute_tail_variate_means> const tail_variate_means = {}; + extractor<tag::abstract_relative_tail_variate_means> const relative_tail_variate_means = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(tail_variate_means) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(relative_tail_variate_means) +} + +using extract::tail_variate_means; +using extract::relative_tail_variate_means; + +// tail_variate_means<LeftRight, VariateType, VariateTag>(absolute) -> absolute_tail_variate_means<LeftRight, VariateType, VariateTag> +template<typename LeftRight, typename VariateType, typename VariateTag> +struct as_feature<tag::tail_variate_means<LeftRight, VariateType, VariateTag>(absolute)> +{ + typedef tag::absolute_tail_variate_means<LeftRight, VariateType, VariateTag> type; +}; + +// tail_variate_means<LeftRight, VariateType, VariateTag>(relative) ->relative_tail_variate_means<LeftRight, VariateType, VariateTag> +template<typename LeftRight, typename VariateType, typename VariateTag> +struct as_feature<tag::tail_variate_means<LeftRight, VariateType, VariateTag>(relative)> +{ + typedef tag::relative_tail_variate_means<LeftRight, VariateType, VariateTag> type; +}; + +// Provides non-templatized extractor +template<typename LeftRight, typename VariateType, typename VariateTag> +struct feature_of<tag::absolute_tail_variate_means<LeftRight, VariateType, VariateTag> > + : feature_of<tag::abstract_absolute_tail_variate_means> +{ +}; + +// Provides non-templatized extractor +template<typename LeftRight, typename VariateType, typename VariateTag> +struct feature_of<tag::relative_tail_variate_means<LeftRight, VariateType, VariateTag> > + : feature_of<tag::abstract_relative_tail_variate_means> +{ +}; + +// So that absolute_tail_means can be automatically substituted +// with absolute_weighted_tail_means when the weight parameter is non-void. +template<typename LeftRight, typename VariateType, typename VariateTag> +struct as_weighted_feature<tag::absolute_tail_variate_means<LeftRight, VariateType, VariateTag> > +{ + typedef tag::absolute_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> type; +}; + +template<typename LeftRight, typename VariateType, typename VariateTag> +struct feature_of<tag::absolute_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> > + : feature_of<tag::absolute_tail_variate_means<LeftRight, VariateType, VariateTag> > +{ +}; + +// So that relative_tail_means can be automatically substituted +// with relative_weighted_tail_means when the weight parameter is non-void. +template<typename LeftRight, typename VariateType, typename VariateTag> +struct as_weighted_feature<tag::relative_tail_variate_means<LeftRight, VariateType, VariateTag> > +{ + typedef tag::relative_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> type; +}; + +template<typename LeftRight, typename VariateType, typename VariateTag> +struct feature_of<tag::relative_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> > + : feature_of<tag::relative_tail_variate_means<LeftRight, VariateType, VariateTag> > +{ +}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif
diff --git a/boost/boost/accumulators/statistics/times2_iterator.hpp b/boost/boost/accumulators/statistics/times2_iterator.hpp new file mode 100644 index 0000000..d46dd04 --- /dev/null +++ b/boost/boost/accumulators/statistics/times2_iterator.hpp
@@ -0,0 +1,62 @@ +/////////////////////////////////////////////////////////////////////////////// +// times2_iterator.hpp +// +// Copyright 2006 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_TIMES2_ITERATOR_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_TIMES2_ITERATOR_HPP_DE_01_01_2006 + +#include <functional> +#include <boost/detail/workaround.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/iterator/transform_iterator.hpp> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/iterator/permutation_iterator.hpp> + +namespace boost { namespace accumulators +{ + +namespace detail +{ + typedef transform_iterator< + std::binder1st<std::multiplies<std::size_t> > + , counting_iterator<std::size_t> + > times2_iterator; + + inline times2_iterator make_times2_iterator(std::size_t i) + { + return make_transform_iterator( + make_counting_iterator(i) + , std::bind1st(std::multiplies<std::size_t>(), 2) + ); + } + + /////////////////////////////////////////////////////////////////////////////// + // lvalue_index_iterator + template<typename Base> + struct lvalue_index_iterator + : Base + { + lvalue_index_iterator() + : Base() + {} + + lvalue_index_iterator(Base base) + : Base(base) + { + } + + typename Base::reference operator [](typename Base::difference_type n) const + { + return *(*this + n); + } + }; +} // namespace detail + +}} + +#endif
diff --git a/boost/boost/accumulators/statistics/variance.hpp b/boost/boost/accumulators/statistics/variance.hpp new file mode 100644 index 0000000..baac556 --- /dev/null +++ b/boost/boost/accumulators/statistics/variance.hpp
@@ -0,0 +1,236 @@ +/////////////////////////////////////////////////////////////////////////////// +// variance.hpp +// +// Copyright 2005 Daniel Egloff, Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_VARIANCE_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_VARIANCE_HPP_EAN_28_10_2005 + +#include <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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/sum.hpp> +#include <boost/accumulators/statistics/mean.hpp> +#include <boost/accumulators/statistics/moment.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + //! Lazy calculation of variance. + /*! + Default sample variance implementation based on the second moment \f$ M_n^{(2)} \f$ moment<2>, mean and count. + \f[ + \sigma_n^2 = M_n^{(2)} - \mu_n^2. + \f] + where + \f[ + \mu_n = \frac{1}{n} \sum_{i = 1}^n x_i. + \f] + is the estimate of the sample mean and \f$n\f$ is the number of samples. + */ + template<typename Sample, typename MeanFeature> + struct lazy_variance_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + lazy_variance_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + extractor<MeanFeature> mean; + result_type tmp = mean(args); + return accumulators::moment<2>(args) - tmp * tmp; + } + }; + + //! Iterative calculation of variance. + /*! + Iterative calculation of sample variance \f$\sigma_n^2\f$ according to the formula + \f[ + \sigma_n^2 = \frac{1}{n} \sum_{i = 1}^n (x_i - \mu_n)^2 = \frac{n-1}{n} \sigma_{n-1}^2 + \frac{1}{n-1}(x_n - \mu_n)^2. + \f] + where + \f[ + \mu_n = \frac{1}{n} \sum_{i = 1}^n x_i. + \f] + is the estimate of the sample mean and \f$n\f$ is the number of samples. + + Note that the sample variance is not defined for \f$n <= 1\f$. + + A simplification can be obtained by the approximate recursion + \f[ + \sigma_n^2 \approx \frac{n-1}{n} \sigma_{n-1}^2 + \frac{1}{n}(x_n - \mu_n)^2. + \f] + because the difference + \f[ + \left(\frac{1}{n-1} - \frac{1}{n}\right)(x_n - \mu_n)^2 = \frac{1}{n(n-1)}(x_n - \mu_n)^2. + \f] + converges to zero as \f$n \rightarrow \infty\f$. However, for small \f$ n \f$ the difference + can be non-negligible. + */ + template<typename Sample, typename MeanFeature, typename Tag> + struct variance_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + template<typename Args> + variance_impl(Args const &args) + : variance(numeric::fdiv(args[sample | Sample()], numeric::one<std::size_t>::value)) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + if(cnt > 1) + { + extractor<MeanFeature> mean; + result_type tmp = args[parameter::keyword<Tag>::get()] - mean(args); + this->variance = + numeric::fdiv(this->variance * (cnt - 1), cnt) + + numeric::fdiv(tmp * tmp, cnt - 1); + } + } + + result_type result(dont_care) const + { + return this->variance; + } + + private: + result_type variance; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::variance +// tag::immediate_variance +// +namespace tag +{ + struct lazy_variance + : depends_on<moment<2>, mean> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::lazy_variance_impl<mpl::_1, mean> impl; + }; + + struct variance + : depends_on<count, immediate_mean> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::variance_impl<mpl::_1, mean, sample> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::lazy_variance +// extract::variance +// +namespace extract +{ + extractor<tag::lazy_variance> const lazy_variance = {}; + extractor<tag::variance> const variance = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(lazy_variance) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(variance) +} + +using extract::lazy_variance; +using extract::variance; + +// variance(lazy) -> lazy_variance +template<> +struct as_feature<tag::variance(lazy)> +{ + typedef tag::lazy_variance type; +}; + +// variance(immediate) -> variance +template<> +struct as_feature<tag::variance(immediate)> +{ + typedef tag::variance type; +}; + +// for the purposes of feature-based dependency resolution, +// immediate_variance provides the same feature as variance +template<> +struct feature_of<tag::lazy_variance> + : feature_of<tag::variance> +{ +}; + +// So that variance can be automatically substituted with +// weighted_variance when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::variance> +{ + typedef tag::weighted_variance type; +}; + +// for the purposes of feature-based dependency resolution, +// weighted_variance provides the same feature as variance +template<> +struct feature_of<tag::weighted_variance> + : feature_of<tag::variance> +{ +}; + +// So that immediate_variance can be automatically substituted with +// immediate_weighted_variance when the weight parameter is non-void. +template<> +struct as_weighted_feature<tag::lazy_variance> +{ + typedef tag::lazy_weighted_variance type; +}; + +// for the purposes of feature-based dependency resolution, +// immediate_weighted_variance provides the same feature as immediate_variance +template<> +struct feature_of<tag::lazy_weighted_variance> + : feature_of<tag::lazy_variance> +{ +}; + +//////////////////////////////////////////////////////////////////////////// +//// droppable_accumulator<variance_impl> +//// need to specialize droppable lazy variance to cache the result at the +//// point the accumulator is dropped. +///// INTERNAL ONLY +///// +//template<typename Sample, typename MeanFeature> +//struct droppable_accumulator<impl::variance_impl<Sample, MeanFeature> > +// : droppable_accumulator_base< +// with_cached_result<impl::variance_impl<Sample, MeanFeature> > +// > +//{ +// template<typename Args> +// droppable_accumulator(Args const &args) +// : droppable_accumulator::base(args) +// { +// } +//}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/variates/covariate.hpp b/boost/boost/accumulators/statistics/variates/covariate.hpp new file mode 100644 index 0000000..aba113a --- /dev/null +++ b/boost/boost/accumulators/statistics/variates/covariate.hpp
@@ -0,0 +1,25 @@ +/////////////////////////////////////////////////////////////////////////////// +// weight.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_VARIATES_COVARIATE_HPP_EAN_03_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_VARIATES_COVARIATE_HPP_EAN_03_11_2005 + +#include <boost/parameter/keyword.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> + +namespace boost { namespace accumulators +{ + +BOOST_PARAMETER_KEYWORD(tag, covariate1) +BOOST_PARAMETER_KEYWORD(tag, covariate2) + +BOOST_ACCUMULATORS_IGNORE_GLOBAL(covariate1) +BOOST_ACCUMULATORS_IGNORE_GLOBAL(covariate2) + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_covariance.hpp b/boost/boost/accumulators/statistics/weighted_covariance.hpp new file mode 100644 index 0000000..25d613c --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_covariance.hpp
@@ -0,0 +1,133 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_covariance.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_COVARIANCE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_COVARIANCE_HPP_DE_01_01_2006 + +#include <vector> +#include <limits> +#include <numeric> +#include <functional> +#include <complex> +#include <boost/mpl/assert.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/range.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/numeric/ublas/io.hpp> +#include <boost/numeric/ublas/matrix.hpp> +#include <boost/type_traits/is_scalar.hpp> +#include <boost/type_traits/is_same.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/covariance.hpp> // for numeric::outer_product() and type traits +#include <boost/accumulators/statistics/weighted_mean.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_covariance_impl + // + /** + @brief Weighted Covariance Estimator + + An iterative Monte Carlo estimator for the weighted covariance \f$\mathrm{Cov}(X,X')\f$, where \f$X\f$ is a sample + and \f$X'\f$ a variate, is given by: + + \f[ + \hat{c}_n = \frac{\bar{w}_n-w_n}{\bar{w}_n} \hat{c}_{n-1} + \frac{w_n}{\bar{w}_n-w_n}(X_n - \hat{\mu}_n)(X_n' - \hat{\mu}_n'), + \quad n\ge2,\quad\hat{c}_1 = 0, + \f] + + \f$\hat{\mu}_n\f$ and \f$\hat{\mu}_n'\f$ being the weighted means of the samples and variates and + \f$\bar{w}_n\f$ the sum of the \f$n\f$ first weights \f$w_i\f$. + */ + template<typename Sample, typename Weight, typename VariateType, typename VariateTag> + struct weighted_covariance_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Weight, typename numeric::functional::fdiv<Sample, std::size_t>::result_type>::result_type weighted_sample_type; + typedef typename numeric::functional::multiplies<Weight, typename numeric::functional::fdiv<VariateType, std::size_t>::result_type>::result_type weighted_variate_type; + // for boost::result_of + typedef typename numeric::functional::outer_product<weighted_sample_type, weighted_variate_type>::result_type result_type; + + template<typename Args> + weighted_covariance_impl(Args const &args) + : cov_( + numeric::outer_product( + numeric::fdiv(args[sample | Sample()], (std::size_t)1) + * numeric::one<Weight>::value + , numeric::fdiv(args[parameter::keyword<VariateTag>::get() | VariateType()], (std::size_t)1) + * numeric::one<Weight>::value + ) + ) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + if (cnt > 1) + { + extractor<tag::weighted_mean_of_variates<VariateType, VariateTag> > const some_weighted_mean_of_variates = {}; + + this->cov_ = this->cov_ * (sum_of_weights(args) - args[weight]) / sum_of_weights(args) + + numeric::outer_product( + some_weighted_mean_of_variates(args) - args[parameter::keyword<VariateTag>::get()] + , weighted_mean(args) - args[sample] + ) * args[weight] / (sum_of_weights(args) - args[weight]); + } + } + + result_type result(dont_care) const + { + return this->cov_; + } + + private: + result_type cov_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_covariance +// +namespace tag +{ + template<typename VariateType, typename VariateTag> + struct weighted_covariance + : depends_on<count, sum_of_weights, weighted_mean, weighted_mean_of_variates<VariateType, VariateTag> > + { + typedef accumulators::impl::weighted_covariance_impl<mpl::_1, mpl::_2, VariateType, VariateTag> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_covariance +// +namespace extract +{ + extractor<tag::abstract_covariance> const weighted_covariance = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_covariance) +} + +using extract::weighted_covariance; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_density.hpp b/boost/boost/accumulators/statistics/weighted_density.hpp new file mode 100644 index 0000000..1407368 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_density.hpp
@@ -0,0 +1,221 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_density.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_DENSITY_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_DENSITY_HPP_DE_01_01_2006 + +#include <vector> +#include <limits> +#include <functional> +#include <boost/range.hpp> +#include <boost/parameter/keyword.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/sum.hpp> +#include <boost/accumulators/statistics/max.hpp> +#include <boost/accumulators/statistics/min.hpp> +#include <boost/accumulators/statistics/density.hpp> // for named parameters density_cache_size and density_num_bins + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_density_impl + // density histogram for weighted samples + /** + @brief Histogram density estimator for weighted samples + + The histogram density estimator returns a histogram of the sample distribution. The positions and sizes of the bins + are determined using a specifiable number of cached samples (cache_size). The range between the minimum and the + maximum of the cached samples is subdivided into a specifiable number of bins (num_bins) of same size. Additionally, + an under- and an overflow bin is added to capture future under- and overflow samples. Once the bins are determined, + the cached samples and all subsequent samples are added to the correct bins. At the end, a range of std::pair is + returned, where each pair contains the position of the bin (lower bound) and the sum of the weights (normalized with the + sum of all weights). + + @param density_cache_size Number of first samples used to determine min and max. + @param density_num_bins Number of bins (two additional bins collect under- and overflow samples). + */ + template<typename Sample, typename Weight> + struct weighted_density_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Weight, 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_density_impl(Args const &args) + : cache_size(args[density_cache_size]) + , cache(cache_size) + , num_bins(args[density_num_bins]) + , samples_in_bin(num_bins + 2, 0.) + , bin_positions(num_bins + 2) + , histogram( + num_bins + 2 + , std::make_pair( + numeric::fdiv(args[sample | Sample()],(std::size_t)1) + , numeric::fdiv(args[sample | Sample()],(std::size_t)1) + ) + ) + , is_dirty(true) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + this->is_dirty = true; + + std::size_t cnt = count(args); + + // Fill up cache with cache_size first samples + if (cnt <= this->cache_size) + { + this->cache[cnt - 1] = std::make_pair(args[sample], args[weight]); + } + + // Once cache_size samples have been accumulated, create num_bins bins of same size between + // the minimum and maximum of the cached samples as well as an under- and an overflow bin. + // Store their lower bounds (bin_positions) and fill the bins with the cached samples (samples_in_bin). + if (cnt == this->cache_size) + { + float_type minimum = numeric::fdiv((min)(args),(std::size_t)1); + float_type maximum = numeric::fdiv((max)(args),(std::size_t)1); + float_type bin_size = numeric::fdiv(maximum - minimum, this->num_bins); + + // determine bin positions (their lower bounds) + for (std::size_t i = 0; i < this->num_bins + 2; ++i) + { + this->bin_positions[i] = minimum + (i - 1.) * bin_size; + } + + for (typename histogram_type::const_iterator iter = this->cache.begin(); iter != this->cache.end(); ++iter) + { + if (iter->first < this->bin_positions[1]) + { + this->samples_in_bin[0] += iter->second; + } + else if (iter->first >= this->bin_positions[this->num_bins + 1]) + { + this->samples_in_bin[this->num_bins + 1] += iter->second; + } + else + { + typename array_type::iterator it = std::upper_bound( + this->bin_positions.begin() + , this->bin_positions.end() + , iter->first + ); + + std::size_t d = std::distance(this->bin_positions.begin(), it); + this->samples_in_bin[d - 1] += iter->second; + } + } + } + // Add each subsequent sample to the correct bin + else if (cnt > this->cache_size) + { + if (args[sample] < this->bin_positions[1]) + { + this->samples_in_bin[0] += args[weight]; + } + else if (args[sample] >= this->bin_positions[this->num_bins + 1]) + { + this->samples_in_bin[this->num_bins + 1] += args[weight]; + } + else + { + typename array_type::iterator it = std::upper_bound( + this->bin_positions.begin() + , this->bin_positions.end() + , args[sample] + ); + + std::size_t d = std::distance(this->bin_positions.begin(), it); + this->samples_in_bin[d - 1] += args[weight]; + } + } + } + + template<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 bin_positions[i] (x-axis of histogram) and + // samples_in_bin[i] / cnt (y-axis of histogram). + + for (std::size_t i = 0; i < this->num_bins + 2; ++i) + { + this->histogram[i] = std::make_pair(this->bin_positions[i], numeric::fdiv(this->samples_in_bin[i], sum_of_weights(args))); + } + } + + // returns a range of pairs + return make_iterator_range(this->histogram); + } + + private: + std::size_t cache_size; // number of cached samples + histogram_type cache; // cache to store the first cache_size samples with their weights as std::pair + std::size_t num_bins; // number of bins + array_type samples_in_bin; // number of samples in each bin + array_type bin_positions; // lower bounds of bins + mutable histogram_type histogram; // histogram + mutable bool is_dirty; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_density +// +namespace tag +{ + struct weighted_density + : depends_on<count, sum_of_weights, min, max> + , density_cache_size + , density_num_bins + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_density_impl<mpl::_1, mpl::_2> impl; + + #ifdef BOOST_ACCUMULATORS_DOXYGEN_INVOKED + static boost::parameter::keyword<density_cache_size> const cache_size; + static boost::parameter::keyword<density_num_bins> const num_bins; + #endif + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_density +// +namespace extract +{ + extractor<tag::density> const weighted_density = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_density) +} + +using extract::weighted_density; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_extended_p_square.hpp b/boost/boost/accumulators/statistics/weighted_extended_p_square.hpp new file mode 100644 index 0000000..ac857e0 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_extended_p_square.hpp
@@ -0,0 +1,290 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_extended_p_square.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_EXTENDED_P_SQUARE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_EXTENDED_P_SQUARE_HPP_DE_01_01_2006 + +#include <vector> +#include <functional> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator_range.hpp> +#include <boost/iterator/transform_iterator.hpp> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/iterator/permutation_iterator.hpp> +#include <boost/parameter/keyword.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/sum.hpp> +#include <boost/accumulators/statistics/times2_iterator.hpp> +#include <boost/accumulators/statistics/extended_p_square.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_extended_p_square_impl + // multiple quantile estimation with weighted samples + /** + @brief Multiple quantile estimation with the extended \f$P^2\f$ algorithm for weighted samples + + This version of the extended \f$P^2\f$ algorithm extends the extended \f$P^2\f$ algorithm to + support weighted samples. The extended \f$P^2\f$ algorithm dynamically estimates several + quantiles without storing samples. Assume that \f$m\f$ quantiles + \f$\xi_{p_1}, \ldots, \xi_{p_m}\f$ are to be estimated. Instead of storing the whole sample + cumulative distribution, the algorithm maintains only \f$m+2\f$ principal markers and + \f$m+1\f$ middle markers, whose positions are updated with each sample and whose heights + are adjusted (if necessary) using a piecewise-parablic formula. The heights of the principal + markers are the current estimates of the quantiles and are returned as an iterator range. + + For further details, see + + K. E. E. Raatikainen, Simultaneous estimation of several quantiles, Simulation, Volume 49, + Number 4 (October), 1986, p. 159-164. + + The extended \f$ P^2 \f$ algorithm generalizes the \f$ P^2 \f$ algorithm of + + R. Jain and I. Chlamtac, The P^2 algorithm for dynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param extended_p_square_probabilities A vector of quantile probabilities. + */ + template<typename Sample, typename Weight> + struct weighted_extended_p_square_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type float_type; + typedef std::vector<float_type> array_type; + // for boost::result_of + typedef iterator_range< + detail::lvalue_index_iterator< + permutation_iterator< + typename array_type::const_iterator + , detail::times2_iterator + > + > + > result_type; + + template<typename Args> + weighted_extended_p_square_impl(Args const &args) + : probabilities( + boost::begin(args[extended_p_square_probabilities]) + , boost::end(args[extended_p_square_probabilities]) + ) + , heights(2 * probabilities.size() + 3) + , actual_positions(heights.size()) + , desired_positions(heights.size()) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + std::size_t sample_cell = 1; // k + std::size_t num_quantiles = this->probabilities.size(); + + // m+2 principal markers and m+1 middle markers + std::size_t num_markers = 2 * num_quantiles + 3; + + // first accumulate num_markers samples + if(cnt <= num_markers) + { + this->heights[cnt - 1] = args[sample]; + this->actual_positions[cnt - 1] = args[weight]; + + // complete the initialization of heights (and actual_positions) by sorting + if(cnt == num_markers) + { + // TODO: we need to sort the initial samples (in heights) in ascending order and + // sort their weights (in actual_positions) the same way. The following lines do + // it, but there must be a better and more efficient way of doing this. + typename array_type::iterator it_begin, it_end, it_min; + + it_begin = this->heights.begin(); + it_end = this->heights.end(); + + std::size_t pos = 0; + + while (it_begin != it_end) + { + it_min = std::min_element(it_begin, it_end); + std::size_t d = std::distance(it_begin, it_min); + std::swap(*it_begin, *it_min); + std::swap(this->actual_positions[pos], this->actual_positions[pos + d]); + ++it_begin; + ++pos; + } + + // calculate correct initial actual positions + for (std::size_t i = 1; i < num_markers; ++i) + { + actual_positions[i] += actual_positions[i - 1]; + } + } + } + else + { + if(args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + this->actual_positions[0] = args[weight]; + sample_cell = 1; + } + else if(args[sample] >= this->heights[num_markers - 1]) + { + this->heights[num_markers - 1] = args[sample]; + sample_cell = num_markers - 1; + } + else + { + // find cell k = sample_cell such that heights[k-1] <= sample < heights[k] + + typedef typename array_type::iterator iterator; + iterator it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // update actual position of all markers above sample_cell + for(std::size_t i = sample_cell; i < num_markers; ++i) + { + this->actual_positions[i] += args[weight]; + } + + // compute desired positions + { + this->desired_positions[0] = this->actual_positions[0]; + this->desired_positions[num_markers - 1] = sum_of_weights(args); + this->desired_positions[1] = (sum_of_weights(args) - this->actual_positions[0]) * probabilities[0] + / 2. + this->actual_positions[0]; + this->desired_positions[num_markers - 2] = (sum_of_weights(args) - this->actual_positions[0]) + * (probabilities[num_quantiles - 1] + 1.) + / 2. + this->actual_positions[0]; + + for (std::size_t i = 0; i < num_quantiles; ++i) + { + this->desired_positions[2 * i + 2] = (sum_of_weights(args) - this->actual_positions[0]) + * probabilities[i] + this->actual_positions[0]; + } + + for (std::size_t i = 1; i < num_quantiles; ++i) + { + this->desired_positions[2 * i + 1] = (sum_of_weights(args) - this->actual_positions[0]) + * (probabilities[i - 1] + probabilities[i]) + / 2. + this->actual_positions[0]; + } + } + + // adjust heights and actual_positions of markers 1 to num_markers - 2 if necessary + for (std::size_t i = 1; i <= num_markers - 2; ++i) + { + // offset to desired position + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i + 1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i - 1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i + 1] - this->heights[i]) / dp; + float_type hm = (this->heights[i - 1] - this->heights[i]) / dm; + + if((d >= 1 && dp > 1) || (d <= -1 && dm < -1)) + { + short sign_d = static_cast<short>(d / std::abs(d)); + + float_type h = this->heights[i] + sign_d / (dp - dm) * ((sign_d - dm)*hp + (dp - sign_d) * hm); + + // try adjusting heights[i] using p-squared formula + if(this->heights[i - 1] < h && h < this->heights[i + 1]) + { + this->heights[i] = h; + } + else + { + // use linear formula + if(d > 0) + { + this->heights[i] += hp; + } + if(d < 0) + { + this->heights[i] -= hm; + } + } + this->actual_positions[i] += sign_d; + } + } + } + } + + result_type result(dont_care) const + { + // for i in [1,probabilities.size()], return heights[i * 2] + detail::times2_iterator idx_begin = detail::make_times2_iterator(1); + detail::times2_iterator idx_end = detail::make_times2_iterator(this->probabilities.size() + 1); + + return result_type( + make_permutation_iterator(this->heights.begin(), idx_begin) + , make_permutation_iterator(this->heights.begin(), idx_end) + ); + } + + private: + array_type probabilities; // the quantile probabilities + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // d_i + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_extended_p_square +// +namespace tag +{ + struct weighted_extended_p_square + : depends_on<count, sum_of_weights> + , extended_p_square_probabilities + { + typedef accumulators::impl::weighted_extended_p_square_impl<mpl::_1, mpl::_2> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_extended_p_square +// +namespace extract +{ + extractor<tag::weighted_extended_p_square> const weighted_extended_p_square = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_extended_p_square) +} + +using extract::weighted_extended_p_square; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_kurtosis.hpp b/boost/boost/accumulators/statistics/weighted_kurtosis.hpp new file mode 100644 index 0000000..3fd4ed7 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_kurtosis.hpp
@@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_kurtosis.hpp +// +// Copyright 2006 Olivier Gygi, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_KURTOSIS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_KURTOSIS_HPP_EAN_28_10_2005 + +#include <limits> +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/weighted_moment.hpp> +#include <boost/accumulators/statistics/weighted_mean.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_kurtosis_impl + /** + @brief Kurtosis estimation for weighted samples + + The kurtosis of a sample distribution is defined as the ratio of the 4th central moment and the square of the 2nd central + moment (the variance) of the samples, minus 3. The term \f$ -3 \f$ is added in order to ensure that the normal distribution + has zero kurtosis. The kurtosis can also be expressed by the simple moments: + + \f[ + \hat{g}_2 = + \frac + {\widehat{m}_n^{(4)}-4\widehat{m}_n^{(3)}\hat{\mu}_n+6\widehat{m}_n^{(2)}\hat{\mu}_n^2-3\hat{\mu}_n^4} + {\left(\widehat{m}_n^{(2)} - \hat{\mu}_n^{2}\right)^2} - 3, + \f] + + where \f$ \widehat{m}_n^{(i)} \f$ are the \f$ i \f$-th moment and \f$ \hat{\mu}_n \f$ the mean (first moment) of the + \f$ n \f$ samples. + + The kurtosis estimator for weighted samples is formally identical to the estimator for unweighted samples, except that + the weighted counterparts of all measures it depends on are to be taken. + */ + template<typename Sample, typename Weight> + struct weighted_kurtosis_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::fdiv<weighted_sample, weighted_sample>::result_type result_type; + + weighted_kurtosis_impl(dont_care) + { + } + + template<typename Args> + result_type result(Args const &args) const + { + return numeric::fdiv( + accumulators::weighted_moment<4>(args) + - 4. * accumulators::weighted_moment<3>(args) * weighted_mean(args) + + 6. * accumulators::weighted_moment<2>(args) * weighted_mean(args) * weighted_mean(args) + - 3. * weighted_mean(args) * weighted_mean(args) * weighted_mean(args) * weighted_mean(args) + , ( accumulators::weighted_moment<2>(args) - weighted_mean(args) * weighted_mean(args) ) + * ( accumulators::weighted_moment<2>(args) - weighted_mean(args) * weighted_mean(args) ) + ) - 3.; + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_kurtosis +// +namespace tag +{ + struct weighted_kurtosis + : depends_on<weighted_mean, weighted_moment<2>, weighted_moment<3>, weighted_moment<4> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_kurtosis_impl<mpl::_1, mpl::_2> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_kurtosis +// +namespace extract +{ + extractor<tag::weighted_kurtosis> const weighted_kurtosis = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_kurtosis) +} + +using extract::weighted_kurtosis; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_mean.hpp b/boost/boost/accumulators/statistics/weighted_mean.hpp new file mode 100644 index 0000000..a80ef09 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_mean.hpp
@@ -0,0 +1,189 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_mean.hpp +// +// Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEAN_HPP_EAN_03_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEAN_HPP_EAN_03_11_2005 + +#include <boost/mpl/assert.hpp> +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/type_traits/is_same.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/weights.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/sum.hpp> +#include <boost/accumulators/statistics/mean.hpp> +#include <boost/accumulators/statistics/weighted_sum.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_mean_impl + // lazy, by default + template<typename Sample, typename Weight, typename Tag> + struct weighted_mean_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::fdiv<weighted_sample, Weight>::result_type result_type; + + weighted_mean_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + typedef + typename mpl::if_< + is_same<Tag, tag::sample> + , tag::weighted_sum + , tag::weighted_sum_of_variates<Sample, Tag> + >::type + weighted_sum_tag; + + extractor<weighted_sum_tag> const some_weighted_sum = {}; + + return numeric::fdiv(some_weighted_sum(args), sum_of_weights(args)); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // immediate_weighted_mean_impl + // immediate + template<typename Sample, typename Weight, typename Tag> + struct immediate_weighted_mean_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::fdiv<weighted_sample, Weight>::result_type result_type; + + template<typename Args> + immediate_weighted_mean_impl(Args const &args) + : mean( + numeric::fdiv( + args[parameter::keyword<Tag>::get() | Sample()] + * numeric::one<Weight>::value + , numeric::one<Weight>::value + ) + ) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + // Matthias: + // need to pass the argument pack since the weight might be an external + // accumulator set passed as a named parameter + Weight w_sum = sum_of_weights(args); + Weight w = args[weight]; + weighted_sample const &s = args[parameter::keyword<Tag>::get()] * w; + this->mean = numeric::fdiv(this->mean * (w_sum - w) + s, w_sum); + } + + result_type result(dont_care) const + { + return this->mean; + } + + private: + result_type mean; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_mean +// tag::immediate_weighted_mean +// +namespace tag +{ + struct weighted_mean + : depends_on<sum_of_weights, weighted_sum> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_mean_impl<mpl::_1, mpl::_2, tag::sample> impl; + }; + struct immediate_weighted_mean + : depends_on<sum_of_weights> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_weighted_mean_impl<mpl::_1, mpl::_2, tag::sample> impl; + }; + template<typename VariateType, typename VariateTag> + struct weighted_mean_of_variates + : depends_on<sum_of_weights, weighted_sum_of_variates<VariateType, VariateTag> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_mean_impl<VariateType, mpl::_2, VariateTag> impl; + }; + template<typename VariateType, typename VariateTag> + struct immediate_weighted_mean_of_variates + : depends_on<sum_of_weights> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::immediate_weighted_mean_impl<VariateType, mpl::_2, VariateTag> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_mean +// extract::weighted_mean_of_variates +// +namespace extract +{ + extractor<tag::mean> const weighted_mean = {}; + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, weighted_mean_of_variates, (typename)(typename)) + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_mean) +} + +using extract::weighted_mean; +using extract::weighted_mean_of_variates; + +// weighted_mean(lazy) -> weighted_mean +template<> +struct as_feature<tag::weighted_mean(lazy)> +{ + typedef tag::weighted_mean type; +}; + +// weighted_mean(immediate) -> immediate_weighted_mean +template<> +struct as_feature<tag::weighted_mean(immediate)> +{ + typedef tag::immediate_weighted_mean type; +}; + +// weighted_mean_of_variates<VariateType, VariateTag>(lazy) -> weighted_mean_of_variates<VariateType, VariateTag> +template<typename VariateType, typename VariateTag> +struct as_feature<tag::weighted_mean_of_variates<VariateType, VariateTag>(lazy)> +{ + typedef tag::weighted_mean_of_variates<VariateType, VariateTag> type; +}; + +// weighted_mean_of_variates<VariateType, VariateTag>(immediate) -> immediate_weighted_mean_of_variates<VariateType, VariateTag> +template<typename VariateType, typename VariateTag> +struct as_feature<tag::weighted_mean_of_variates<VariateType, VariateTag>(immediate)> +{ + typedef tag::immediate_weighted_mean_of_variates<VariateType, VariateTag> type; +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_median.hpp b/boost/boost/accumulators/statistics/weighted_median.hpp new file mode 100644 index 0000000..ed7cadb --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_median.hpp
@@ -0,0 +1,237 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_median.hpp +// +// Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEDIAN_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MEDIAN_HPP_EAN_28_10_2005 + +#include <boost/mpl/placeholders.hpp> +#include <boost/range/iterator_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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#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_cumul_dist.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_median_impl + // + /** + @brief Median estimation for weighted samples based on the \f$P^2\f$ quantile estimator + + The \f$P^2\f$ algorithm for weighted samples is invoked with a quantile probability of 0.5. + */ + template<typename Sample> + struct weighted_median_impl + : accumulator_base + { + // for boost::result_of + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type result_type; + + weighted_median_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + return weighted_p_square_quantile_for_median(args); + } + }; + + /////////////////////////////////////////////////////////////////////////////// + // with_density_weighted_median_impl + // + /** + @brief Median estimation for weighted samples based on the density estimator + + The algorithm determines the bin in which the \f$0.5*cnt\f$-th sample lies, \f$cnt\f$ being + the total number of samples. It returns the approximate horizontal position of this sample, + based on a linear interpolation inside the bin. + */ + template<typename Sample> + struct with_density_weighted_median_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type; + typedef std::vector<std::pair<float_type, float_type> > histogram_type; + typedef iterator_range<typename histogram_type::iterator> range_type; + // for boost::result_of + typedef float_type result_type; + + template<typename Args> + with_density_weighted_median_impl(Args const &args) + : sum(numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , is_dirty(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty = true; + } + + template<typename Args> + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + std::size_t cnt = count(args); + range_type histogram = weighted_density(args); + typename range_type::iterator it = histogram.begin(); + while (this->sum < 0.5 * cnt) + { + this->sum += it->second * cnt; + ++it; + } + --it; + float_type over = numeric::fdiv(this->sum - 0.5 * cnt, it->second * cnt); + this->median = it->first * over + (it + 1)->first * ( 1. - over ); + } + + return this->median; + } + + private: + mutable float_type sum; + mutable bool is_dirty; + mutable float_type median; + }; + + /////////////////////////////////////////////////////////////////////////////// + // with_p_square_cumulative_distribution_weighted_median_impl + // + /** + @brief Median estimation for weighted samples based on the \f$P^2\f$ cumulative distribution estimator + + The algorithm determines the first (leftmost) bin with a height exceeding 0.5. It + returns the approximate horizontal position of where the cumulative distribution + equals 0.5, based on a linear interpolation inside the bin. + */ + template<typename Sample, typename Weight> + struct with_p_square_cumulative_distribution_weighted_median_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type float_type; + typedef std::vector<std::pair<float_type, float_type> > histogram_type; + typedef iterator_range<typename histogram_type::iterator> range_type; + // for boost::result_of + typedef float_type result_type; + + with_p_square_cumulative_distribution_weighted_median_impl(dont_care) + : is_dirty(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty = true; + } + + template<typename Args> + result_type result(Args const &args) const + { + if (this->is_dirty) + { + this->is_dirty = false; + + range_type histogram = weighted_p_square_cumulative_distribution(args); + typename range_type::iterator it = histogram.begin(); + while (it->second < 0.5) + { + ++it; + } + float_type over = numeric::fdiv(it->second - 0.5, it->second - (it - 1)->second); + this->median = it->first * over + (it + 1)->first * ( 1. - over ); + } + + return this->median; + } + private: + mutable bool is_dirty; + mutable float_type median; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_median +// tag::with_density_weighted_median +// tag::with_p_square_cumulative_distribution_weighted_median +// +namespace tag +{ + struct weighted_median + : depends_on<weighted_p_square_quantile_for_median> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_median_impl<mpl::_1> impl; + }; + struct with_density_weighted_median + : depends_on<count, weighted_density> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::with_density_weighted_median_impl<mpl::_1> impl; + }; + struct with_p_square_cumulative_distribution_weighted_median + : depends_on<weighted_p_square_cumulative_distribution> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::with_p_square_cumulative_distribution_weighted_median_impl<mpl::_1, mpl::_2> impl; + }; + +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_median +// +namespace extract +{ + extractor<tag::median> const weighted_median = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_median) +} + +using extract::weighted_median; +// weighted_median(with_p_square_quantile) -> weighted_median +template<> +struct as_feature<tag::weighted_median(with_p_square_quantile)> +{ + typedef tag::weighted_median type; +}; + +// weighted_median(with_density) -> with_density_weighted_median +template<> +struct as_feature<tag::weighted_median(with_density)> +{ + typedef tag::with_density_weighted_median type; +}; + +// weighted_median(with_p_square_cumulative_distribution) -> with_p_square_cumulative_distribution_weighted_median +template<> +struct as_feature<tag::weighted_median(with_p_square_cumulative_distribution)> +{ + typedef tag::with_p_square_cumulative_distribution_weighted_median type; +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_moment.hpp b/boost/boost/accumulators/statistics/weighted_moment.hpp new file mode 100644 index 0000000..011701c --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_moment.hpp
@@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_moment.hpp +// +// Copyright 2006, Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MOMENT_HPP_EAN_15_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_MOMENT_HPP_EAN_15_11_2005 + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/mpl/int.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/preprocessor/arithmetic/inc.hpp> +#include <boost/preprocessor/repetition/repeat_from_to.hpp> +#include <boost/preprocessor/repetition/enum_trailing_params.hpp> +#include <boost/preprocessor/repetition/enum_trailing_binary_params.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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/moment.hpp> // for pow() +#include <boost/accumulators/statistics/sum.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_moment_impl + template<typename N, typename Sample, typename Weight> + struct weighted_moment_impl + : accumulator_base // TODO: also depends_on sum of powers + { + BOOST_MPL_ASSERT_RELATION(N::value, >, 0); + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::fdiv<weighted_sample, Weight>::result_type result_type; + + template<typename Args> + weighted_moment_impl(Args const &args) + : sum(args[sample | Sample()] * numeric::one<Weight>::value) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + this->sum += args[weight] * numeric::pow(args[sample], N()); + } + + template<typename Args> + result_type result(Args const &args) const + { + return numeric::fdiv(this->sum, sum_of_weights(args)); + } + + private: + weighted_sample sum; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_moment +// +namespace tag +{ + template<int N> + struct weighted_moment + : depends_on<count, sum_of_weights> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_moment_impl<mpl::int_<N>, mpl::_1, mpl::_2> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_moment +// +namespace extract +{ + BOOST_ACCUMULATORS_DEFINE_EXTRACTOR(tag, weighted_moment, (int)) +} + +using extract::weighted_moment; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp b/boost/boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp new file mode 100644 index 0000000..ce750ed --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp
@@ -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 algorithm 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::fdiv<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::fdiv((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::fdiv(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
diff --git a/boost/boost/accumulators/statistics/weighted_p_square_cumulative_distribution.hpp b/boost/boost/accumulators/statistics/weighted_p_square_cumulative_distribution.hpp new file mode 100644 index 0000000..918970e --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_p_square_cumulative_distribution.hpp
@@ -0,0 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_p_square_cumulative_distribution.hpp +// +// 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_03_19_2012 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_CUMULATIVE_DISTRIBUTION_HPP_03_19_2012 + +#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 + +#include <boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp> + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_p_square_quantile.hpp b/boost/boost/accumulators/statistics/weighted_p_square_quantile.hpp new file mode 100644 index 0000000..2ebc7b1 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_p_square_quantile.hpp
@@ -0,0 +1,255 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_p_square_quantile.hpp +// +// Copyright 2005 Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_P_SQUARE_QUANTILE_HPP_DE_01_01_2006 + +#include <cmath> +#include <functional> +#include <boost/array.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/type_traits/is_same.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/parameters/quantile_probability.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl { + /////////////////////////////////////////////////////////////////////////////// + // weighted_p_square_quantile_impl + // single quantile estimation with weighted samples + /** + @brief Single quantile estimation with the \f$P^2\f$ algorithm for weighted samples + + This version of the \f$P^2\f$ algorithm extends the \f$P^2\f$ algorithm to support weighted samples. + The \f$P^2\f$ algorithm estimates a quantile dynamically without storing samples. Instead of + storing the whole sample cumulative distribution, only five points (markers) are stored. The heights + of these markers are the minimum and the maximum of the samples and the current estimates of the + \f$(p/2)\f$-, \f$p\f$ - and \f$(1+p)/2\f$ -quantiles. Their positions are equal to the number + of samples that are smaller or equal to the markers. Each time a new sample is added, the + positions of the markers are updated and if necessary their heights are adjusted using a piecewise- + parabolic formula. + + For further details, see + + R. Jain and I. Chlamtac, The P^2 algorithm for dynamic calculation of quantiles and + histograms without storing observations, Communications of the ACM, + Volume 28 (October), Number 10, 1985, p. 1076-1085. + + @param quantile_probability + */ + template<typename Sample, typename Weight, typename Impl> + struct weighted_p_square_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type float_type; + typedef array<float_type, 5> array_type; + // for boost::result_of + typedef float_type result_type; + + template<typename Args> + weighted_p_square_quantile_impl(Args const &args) + : p(is_same<Impl, for_median>::value ? 0.5 : args[quantile_probability | 0.5]) + , heights() + , actual_positions() + , desired_positions() + { + } + + template<typename Args> + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + // accumulate 5 first samples + if (cnt <= 5) + { + this->heights[cnt - 1] = args[sample]; + + // In this initialization phase, actual_positions stores the weights of the + // initial samples that are needed at the end of the initialization phase to + // compute the correct initial positions of the markers. + this->actual_positions[cnt - 1] = args[weight]; + + // complete the initialization of heights and actual_positions by sorting + if (cnt == 5) + { + // TODO: we need to sort the initial samples (in heights) in ascending order and + // sort their weights (in actual_positions) the same way. The following lines do + // it, but there must be a better and more efficient way of doing this. + typename array_type::iterator it_begin, it_end, it_min; + + it_begin = this->heights.begin(); + it_end = this->heights.end(); + + std::size_t pos = 0; + + while (it_begin != it_end) + { + it_min = std::min_element(it_begin, it_end); + std::size_t d = std::distance(it_begin, it_min); + std::swap(*it_begin, *it_min); + std::swap(this->actual_positions[pos], this->actual_positions[pos + d]); + ++it_begin; + ++pos; + } + + // calculate correct initial actual positions + for (std::size_t i = 1; i < 5; ++i) + { + this->actual_positions[i] += this->actual_positions[i - 1]; + } + } + } + else + { + std::size_t sample_cell = 1; // k + + // find cell k such that heights[k-1] <= args[sample] < heights[k] and adjust extreme values + if (args[sample] < this->heights[0]) + { + this->heights[0] = args[sample]; + this->actual_positions[0] = args[weight]; + sample_cell = 1; + } + else if (this->heights[4] <= args[sample]) + { + this->heights[4] = args[sample]; + sample_cell = 4; + } + else + { + typedef typename array_type::iterator iterator; + iterator it = std::upper_bound( + this->heights.begin() + , this->heights.end() + , args[sample] + ); + + sample_cell = std::distance(this->heights.begin(), it); + } + + // increment positions of markers above sample_cell + for (std::size_t i = sample_cell; i < 5; ++i) + { + this->actual_positions[i] += args[weight]; + } + + // update desired positions for all markers + this->desired_positions[0] = this->actual_positions[0]; + this->desired_positions[1] = (sum_of_weights(args) - this->actual_positions[0]) + * this->p/2. + this->actual_positions[0]; + this->desired_positions[2] = (sum_of_weights(args) - this->actual_positions[0]) + * this->p + this->actual_positions[0]; + this->desired_positions[3] = (sum_of_weights(args) - this->actual_positions[0]) + * (1. + this->p)/2. + this->actual_positions[0]; + this->desired_positions[4] = sum_of_weights(args); + + // adjust height and actual positions of markers 1 to 3 if necessary + for (std::size_t i = 1; i <= 3; ++i) + { + // offset to desired positions + float_type d = this->desired_positions[i] - this->actual_positions[i]; + + // offset to next position + float_type dp = this->actual_positions[i + 1] - this->actual_positions[i]; + + // offset to previous position + float_type dm = this->actual_positions[i - 1] - this->actual_positions[i]; + + // height ds + float_type hp = (this->heights[i + 1] - this->heights[i]) / dp; + float_type hm = (this->heights[i - 1] - this->heights[i]) / dm; + + if ( ( d >= 1. && dp > 1. ) || ( d <= -1. && dm < -1. ) ) + { + short sign_d = static_cast<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; + } + } + } + } + + result_type result(dont_care) const + { + return this->heights[2]; + } + + private: + float_type p; // the quantile probability p + array_type heights; // q_i + array_type actual_positions; // n_i + array_type desired_positions; // n'_i + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_p_square_quantile +// +namespace tag +{ + struct weighted_p_square_quantile + : depends_on<count, sum_of_weights> + { + typedef accumulators::impl::weighted_p_square_quantile_impl<mpl::_1, mpl::_2, regular> impl; + }; + struct weighted_p_square_quantile_for_median + : depends_on<count, sum_of_weights> + { + typedef accumulators::impl::weighted_p_square_quantile_impl<mpl::_1, mpl::_2, for_median> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_p_square_quantile +// extract::weighted_p_square_quantile_for_median +// +namespace extract +{ + extractor<tag::weighted_p_square_quantile> const weighted_p_square_quantile = {}; + extractor<tag::weighted_p_square_quantile_for_median> const weighted_p_square_quantile_for_median = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_p_square_quantile) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_p_square_quantile_for_median) +} + +using extract::weighted_p_square_quantile; +using extract::weighted_p_square_quantile_for_median; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp b/boost/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp new file mode 100644 index 0000000..418b38c --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_peaks_over_threshold.hpp
@@ -0,0 +1,289 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_peaks_over_threshold.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_PEAKS_OVER_THRESHOLD_HPP_DE_01_01_2006 + +#include <vector> +#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> +#include <boost/parameter/keyword.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> +#include <boost/accumulators/statistics/peaks_over_threshold.hpp> // for named parameters pot_threshold_value and pot_threshold_probability +#include <boost/accumulators/statistics/sum.hpp> +#include <boost/accumulators/statistics/tail_variate.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + /////////////////////////////////////////////////////////////////////////////// + // weighted_peaks_over_threshold_impl + // works with an explicit threshold value and does not depend on order statistics of weighted samples + /** + @brief Weighted Peaks over Threshold Method for Weighted Quantile and Weighted Tail Mean Estimation + + @sa peaks_over_threshold_impl + + @param quantile_probability + @param pot_threshold_value + */ + template<typename Sample, typename Weight, typename LeftRight> + struct weighted_peaks_over_threshold_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Weight, Sample>::result_type weighted_sample; + typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type float_type; + // for boost::result_of + typedef boost::tuple<float_type, float_type, float_type> result_type; + + template<typename Args> + weighted_peaks_over_threshold_impl(Args const &args) + : sign_((is_same<LeftRight, left>::value) ? -1 : 1) + , mu_(sign_ * numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , sigma2_(numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , w_sum_(numeric::fdiv(args[weight | Weight()], (std::size_t)1)) + , threshold_(sign_ * args[pot_threshold_value]) + , fit_parameters_(boost::make_tuple(0., 0., 0.)) + , is_dirty_(true) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + this->is_dirty_ = true; + + if (this->sign_ * args[sample] > this->threshold_) + { + this->mu_ += args[weight] * args[sample]; + this->sigma2_ += args[weight] * args[sample] * args[sample]; + this->w_sum_ += args[weight]; + } + } + + template<typename Args> + result_type result(Args const &args) const + { + if (this->is_dirty_) + { + this->is_dirty_ = false; + + this->mu_ = this->sign_ * numeric::fdiv(this->mu_, this->w_sum_); + this->sigma2_ = numeric::fdiv(this->sigma2_, this->w_sum_); + this->sigma2_ -= this->mu_ * this->mu_; + + float_type threshold_probability = numeric::fdiv(sum_of_weights(args) - this->w_sum_, sum_of_weights(args)); + + float_type tmp = numeric::fdiv(( this->mu_ - this->threshold_ )*( this->mu_ - this->threshold_ ), this->sigma2_); + float_type xi_hat = 0.5 * ( 1. - tmp ); + float_type beta_hat = 0.5 * ( this->mu_ - this->threshold_ ) * ( 1. + tmp ); + float_type beta_bar = beta_hat * std::pow(1. - threshold_probability, xi_hat); + float_type u_bar = this->threshold_ - beta_bar * ( std::pow(1. - threshold_probability, -xi_hat) - 1.)/xi_hat; + this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat); + } + + return this->fit_parameters_; + } + + private: + short sign_; // for left tail fitting, mirror the extreme values + mutable float_type mu_; // mean of samples above threshold + mutable float_type sigma2_; // variance of samples above threshold + mutable float_type w_sum_; // sum of weights of samples above threshold + float_type threshold_; + mutable result_type fit_parameters_; // boost::tuple that stores fit parameters + mutable bool is_dirty_; + }; + + /////////////////////////////////////////////////////////////////////////////// + // weighted_peaks_over_threshold_prob_impl + // determines threshold from a given threshold probability using order statistics + /** + @brief Peaks over Threshold Method for Quantile and Tail Mean Estimation + + @sa weighted_peaks_over_threshold_impl + + @param quantile_probability + @param pot_threshold_probability + */ + template<typename Sample, typename Weight, typename LeftRight> + struct weighted_peaks_over_threshold_prob_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Weight, Sample>::result_type weighted_sample; + typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type float_type; + // for boost::result_of + typedef boost::tuple<float_type, float_type, float_type> result_type; + + template<typename Args> + weighted_peaks_over_threshold_prob_impl(Args const &args) + : sign_((is_same<LeftRight, left>::value) ? -1 : 1) + , mu_(sign_ * numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , sigma2_(numeric::fdiv(args[sample | Sample()], (std::size_t)1)) + , threshold_probability_(args[pot_threshold_probability]) + , fit_parameters_(boost::make_tuple(0., 0., 0.)) + , is_dirty_(true) + { + } + + void operator ()(dont_care) + { + this->is_dirty_ = true; + } + + template<typename Args> + result_type result(Args const &args) const + { + if (this->is_dirty_) + { + this->is_dirty_ = false; + + float_type threshold = sum_of_weights(args) + * ( ( is_same<LeftRight, left>::value ) ? this->threshold_probability_ : 1. - this->threshold_probability_ ); + + std::size_t n = 0; + Weight sum = Weight(0); + + while (sum < threshold) + { + if (n < static_cast<std::size_t>(tail_weights(args).size())) + { + mu_ += *(tail_weights(args).begin() + n) * *(tail(args).begin() + n); + sigma2_ += *(tail_weights(args).begin() + n) * *(tail(args).begin() + n) * (*(tail(args).begin() + n)); + sum += *(tail_weights(args).begin() + n); + n++; + } + else + { + if (std::numeric_limits<float_type>::has_quiet_NaN) + { + return boost::make_tuple( + std::numeric_limits<float_type>::quiet_NaN() + , std::numeric_limits<float_type>::quiet_NaN() + , std::numeric_limits<float_type>::quiet_NaN() + ); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return boost::make_tuple(Sample(0), Sample(0), Sample(0)); + } + } + } + + float_type u = *(tail(args).begin() + n - 1) * this->sign_; + + + this->mu_ = this->sign_ * numeric::fdiv(this->mu_, sum); + this->sigma2_ = numeric::fdiv(this->sigma2_, sum); + this->sigma2_ -= this->mu_ * this->mu_; + + if (is_same<LeftRight, left>::value) + this->threshold_probability_ = 1. - this->threshold_probability_; + + float_type tmp = numeric::fdiv(( this->mu_ - u )*( this->mu_ - u ), this->sigma2_); + float_type xi_hat = 0.5 * ( 1. - tmp ); + float_type beta_hat = 0.5 * ( this->mu_ - u ) * ( 1. + tmp ); + float_type beta_bar = beta_hat * std::pow(1. - threshold_probability_, xi_hat); + float_type u_bar = u - beta_bar * ( std::pow(1. - threshold_probability_, -xi_hat) - 1.)/xi_hat; + this->fit_parameters_ = boost::make_tuple(u_bar, beta_bar, xi_hat); + + } + + return this->fit_parameters_; + } + + private: + short sign_; // for left tail fitting, mirror the extreme values + mutable float_type mu_; // mean of samples above threshold u + mutable float_type sigma2_; // variance of samples above threshold u + mutable float_type threshold_probability_; + mutable result_type fit_parameters_; // boost::tuple that stores fit parameters + mutable bool is_dirty_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_peaks_over_threshold +// +namespace tag +{ + template<typename LeftRight> + struct weighted_peaks_over_threshold + : depends_on<sum_of_weights> + , pot_threshold_value + { + /// INTERNAL ONLY + typedef accumulators::impl::weighted_peaks_over_threshold_impl<mpl::_1, mpl::_2, LeftRight> impl; + }; + + template<typename LeftRight> + struct weighted_peaks_over_threshold_prob + : depends_on<sum_of_weights, tail_weights<LeftRight> > + , pot_threshold_probability + { + /// INTERNAL ONLY + typedef accumulators::impl::weighted_peaks_over_threshold_prob_impl<mpl::_1, mpl::_2, LeftRight> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_peaks_over_threshold +// +namespace extract +{ + extractor<tag::abstract_peaks_over_threshold> const weighted_peaks_over_threshold = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_peaks_over_threshold) +} + +using extract::weighted_peaks_over_threshold; + +// weighted_peaks_over_threshold<LeftRight>(with_threshold_value) -> weighted_peaks_over_threshold<LeftRight> +template<typename LeftRight> +struct as_feature<tag::weighted_peaks_over_threshold<LeftRight>(with_threshold_value)> +{ + typedef tag::weighted_peaks_over_threshold<LeftRight> type; +}; + +// weighted_peaks_over_threshold<LeftRight>(with_threshold_probability) -> weighted_peaks_over_threshold_prob<LeftRight> +template<typename LeftRight> +struct as_feature<tag::weighted_peaks_over_threshold<LeftRight>(with_threshold_probability)> +{ + typedef tag::weighted_peaks_over_threshold_prob<LeftRight> type; +}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_skewness.hpp b/boost/boost/accumulators/statistics/weighted_skewness.hpp new file mode 100644 index 0000000..a3ac387 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_skewness.hpp
@@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_skewness.hpp +// +// Copyright 2006 Olivier Gygi, Daniel Egloff. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SKEWNESS_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SKEWNESS_HPP_EAN_28_10_2005 + +#include <limits> +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/weighted_moment.hpp> +#include <boost/accumulators/statistics/weighted_mean.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_skewness_impl + /** + @brief Skewness estimation for weighted samples + + The skewness of a sample distribution is defined as the ratio of the 3rd central moment and the \f$ 3/2 \f$-th power $ + of the 2nd central moment (the variance) of the samples. The skewness can also be expressed by the simple moments: + + \f[ + \hat{g}_1 = + \frac + {\widehat{m}_n^{(3)}-3\widehat{m}_n^{(2)}\hat{\mu}_n+2\hat{\mu}_n^3} + {\left(\widehat{m}_n^{(2)} - \hat{\mu}_n^{2}\right)^{3/2}} + \f] + + where \f$ \widehat{m}_n^{(i)} \f$ are the \f$ i \f$-th moment and \f$ \hat{\mu}_n \f$ the mean (first moment) of the + \f$ n \f$ samples. + + The skewness estimator for weighted samples is formally identical to the estimator for unweighted samples, except that + the weighted counterparts of all measures it depends on are to be taken. + */ + template<typename Sample, typename Weight> + struct weighted_skewness_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::fdiv<weighted_sample, weighted_sample>::result_type result_type; + + weighted_skewness_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + return numeric::fdiv( + accumulators::weighted_moment<3>(args) + - 3. * accumulators::weighted_moment<2>(args) * weighted_mean(args) + + 2. * weighted_mean(args) * weighted_mean(args) * weighted_mean(args) + , ( accumulators::weighted_moment<2>(args) - weighted_mean(args) * weighted_mean(args) ) + * std::sqrt( accumulators::weighted_moment<2>(args) - weighted_mean(args) * weighted_mean(args) ) + ); + } + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_skewness +// +namespace tag +{ + struct weighted_skewness + : depends_on<weighted_mean, weighted_moment<2>, weighted_moment<3> > + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_skewness_impl<mpl::_1, mpl::_2> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_skewness +// +namespace extract +{ + extractor<tag::weighted_skewness> const weighted_skewness = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_skewness) +} + +using extract::weighted_skewness; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_sum.hpp b/boost/boost/accumulators/statistics/weighted_sum.hpp new file mode 100644 index 0000000..2715390 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_sum.hpp
@@ -0,0 +1,116 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_sum.hpp +// +// Copyright 2006 Eric Niebler, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SUM_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SUM_HPP_EAN_28_10_2005 + +#include <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/framework/parameters/weight.hpp> +#include <boost/accumulators/framework/accumulators/external_accumulator.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_sum_impl + template<typename Sample, typename Weight, typename Tag> + struct weighted_sum_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + + // for boost::result_of + typedef weighted_sample result_type; + + template<typename Args> + weighted_sum_impl(Args const &args) + : weighted_sum_( + args[parameter::keyword<Tag>::get() | Sample()] + * numeric::one<Weight>::value + ) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + // what about overflow? + this->weighted_sum_ += args[parameter::keyword<Tag>::get()] * args[weight]; + } + + result_type result(dont_care) const + { + return this->weighted_sum_; + } + + private: + + weighted_sample weighted_sum_; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_sum +// +namespace tag +{ + struct weighted_sum + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_sum_impl<mpl::_1, mpl::_2, tag::sample> impl; + }; + + template<typename VariateType, typename VariateTag> + struct weighted_sum_of_variates + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_sum_impl<VariateType, mpl::_2, VariateTag> impl; + }; + + struct abstract_weighted_sum_of_variates + : depends_on<> + { + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_sum +// +namespace extract +{ + extractor<tag::weighted_sum> const weighted_sum = {}; + extractor<tag::abstract_weighted_sum_of_variates> const weighted_sum_of_variates = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_sum) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_sum_of_variates) +} + +using extract::weighted_sum; +using extract::weighted_sum_of_variates; + +template<typename VariateType, typename VariateTag> +struct feature_of<tag::weighted_sum_of_variates<VariateType, VariateTag> > + : feature_of<tag::abstract_weighted_sum_of_variates> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_sum_kahan.hpp b/boost/boost/accumulators/statistics/weighted_sum_kahan.hpp new file mode 100644 index 0000000..fbb0303 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_sum_kahan.hpp
@@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_sum_kahan.hpp +// +// Copyright 2011 Simon West. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SUM_KAHAN_HPP_EAN_11_05_2011 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_SUM_KAHAN_HPP_EAN_11_05_2011 + +#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/framework/parameters/weight.hpp> +#include <boost/accumulators/framework/accumulators/external_accumulator.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/weighted_sum.hpp> +#include <boost/numeric/conversion/cast.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ +#if _MSC_VER > 1400 +# pragma float_control(push) +# pragma float_control(precise, on) +#endif + + /////////////////////////////////////////////////////////////////////////////// + // weighted_sum_kahan_impl + template<typename Sample, typename Weight, typename Tag> + struct weighted_sum_kahan_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + + // for boost::result_of + typedef weighted_sample result_type; + + template<typename Args> + weighted_sum_kahan_impl(Args const &args) + : weighted_sum_( + args[parameter::keyword<Tag>::get() | Sample()] * numeric::one<Weight>::value), + compensation(boost::numeric_cast<weighted_sample>(0.0)) + { + } + + template<typename Args> + void +#if BOOST_ACCUMULATORS_GCC_VERSION > 40305 + __attribute__((__optimize__("no-associative-math"))) +#endif + operator ()(Args const &args) + { + const weighted_sample myTmp1 = args[parameter::keyword<Tag>::get()] * args[weight] - this->compensation; + const weighted_sample myTmp2 = this->weighted_sum_ + myTmp1; + this->compensation = (myTmp2 - this->weighted_sum_) - myTmp1; + this->weighted_sum_ = myTmp2; + + } + + result_type result(dont_care) const + { + return this->weighted_sum_; + } + + private: + weighted_sample weighted_sum_; + weighted_sample compensation; + }; + +#if _MSC_VER > 1400 +# pragma float_control(pop) +#endif + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_sum_kahan +// tag::weighted_sum_of_variates_kahan +// +namespace tag +{ + struct weighted_sum_kahan + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_sum_kahan_impl<mpl::_1, mpl::_2, tag::sample> impl; + }; + + template<typename VariateType, typename VariateTag> + struct weighted_sum_of_variates_kahan + : depends_on<> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_sum_kahan_impl<VariateType, mpl::_2, VariateTag> impl; + }; + +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_sum_kahan +// extract::weighted_sum_of_variates_kahan +// +namespace extract +{ + extractor<tag::weighted_sum_kahan> const weighted_sum_kahan = {}; + extractor<tag::abstract_weighted_sum_of_variates> const weighted_sum_of_variates_kahan = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_sum_kahan) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_sum_of_variates_kahan) +} + +using extract::weighted_sum_kahan; +using extract::weighted_sum_of_variates_kahan; + +// weighted_sum(kahan) -> weighted_sum_kahan +template<> +struct as_feature<tag::weighted_sum(kahan)> +{ + typedef tag::weighted_sum_kahan type; +}; + +template<typename VariateType, typename VariateTag> +struct feature_of<tag::weighted_sum_of_variates_kahan<VariateType, VariateTag> > + : feature_of<tag::abstract_weighted_sum_of_variates> +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_tail_mean.hpp b/boost/boost/accumulators/statistics/weighted_tail_mean.hpp new file mode 100644 index 0000000..bae8530 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_tail_mean.hpp
@@ -0,0 +1,169 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_tail_mean.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_MEAN_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_MEAN_HPP_DE_01_01_2006 + +#include <numeric> +#include <vector> +#include <limits> +#include <functional> +#include <sstream> +#include <stdexcept> +#include <boost/throw_exception.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/tail.hpp> +#include <boost/accumulators/statistics/tail_mean.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + + /////////////////////////////////////////////////////////////////////////////// + // coherent_weighted_tail_mean_impl + // + // TODO + + /////////////////////////////////////////////////////////////////////////////// + // non_coherent_weighted_tail_mean_impl + // + /** + @brief Estimation of the (non-coherent) weighted tail mean based on order statistics (for both left and right tails) + + + + An estimation of the non-coherent, weighted tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$ is given by the weighted mean + of the + + \f[ + \lambda = \inf\left\{ l \left| \frac{1}{\bar{w}_n}\sum_{i=1}^{l} w_i \geq \alpha \right. \right\} + \f] + + smallest samples (left tail) or the weighted mean of the + + \f[ + n + 1 - \rho = n + 1 - \sup\left\{ r \left| \frac{1}{\bar{w}_n}\sum_{i=r}^{n} w_i \geq (1 - \alpha) \right. \right\} + \f] + + largest samples (right tail) above a quantile \f$\hat{q}_{\alpha}\f$ of level \f$\alpha\f$, \f$n\f$ being the total number of sample + and \f$\bar{w}_n\f$ the sum of all \f$n\f$ weights: + + \f[ + \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X) = \frac{\sum_{i=1}^{\lambda} w_i X_{i:n}}{\sum_{i=1}^{\lambda} w_i}, + \f] + + \f[ + \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X) = \frac{\sum_{i=\rho}^n w_i X_{i:n}}{\sum_{i=\rho}^n w_i}. + \f] + + @param quantile_probability + */ + template<typename Sample, typename Weight, typename LeftRight> + struct non_coherent_weighted_tail_mean_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + typedef typename numeric::functional::fdiv<Weight, std::size_t>::result_type float_type; + // for boost::result_of + typedef typename numeric::functional::fdiv<weighted_sample, std::size_t>::result_type result_type; + + non_coherent_weighted_tail_mean_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + float_type threshold = sum_of_weights(args) + * ( ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ); + + std::size_t n = 0; + Weight sum = Weight(0); + + while (sum < threshold) + { + if (n < static_cast<std::size_t>(tail_weights(args).size())) + { + sum += *(tail_weights(args).begin() + n); + n++; + } + else + { + if (std::numeric_limits<result_type>::has_quiet_NaN) + { + return std::numeric_limits<result_type>::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return result_type(0); + } + } + } + + return numeric::fdiv( + std::inner_product( + tail(args).begin() + , tail(args).begin() + n + , tail_weights(args).begin() + , weighted_sample(0) + ) + , sum + ); + } + }; + +} // namespace impl + + +/////////////////////////////////////////////////////////////////////////////// +// tag::non_coherent_weighted_tail_mean<> +// +namespace tag +{ + template<typename LeftRight> + struct non_coherent_weighted_tail_mean + : depends_on<sum_of_weights, tail_weights<LeftRight> > + { + typedef accumulators::impl::non_coherent_weighted_tail_mean_impl<mpl::_1, mpl::_2, LeftRight> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::non_coherent_weighted_tail_mean; +// +namespace extract +{ + extractor<tag::abstract_non_coherent_tail_mean> const non_coherent_weighted_tail_mean = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(non_coherent_weighted_tail_mean) +} + +using extract::non_coherent_weighted_tail_mean; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_tail_quantile.hpp b/boost/boost/accumulators/statistics/weighted_tail_quantile.hpp new file mode 100644 index 0000000..b143457 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_tail_quantile.hpp
@@ -0,0 +1,146 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_tail_quantile.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_QUANTILE_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_QUANTILE_HPP_DE_01_01_2006 + +#include <vector> +#include <limits> +#include <functional> +#include <sstream> +#include <stdexcept> +#include <boost/throw_exception.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/mpl/if.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/tail.hpp> +#include <boost/accumulators/statistics/tail_quantile.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // weighted_tail_quantile_impl + // Tail quantile estimation based on order statistics of weighted samples + /** + @brief Tail quantile estimation based on order statistics of weighted samples (for both left and right tails) + + An estimator \f$\hat{q}\f$ of tail quantiles with level \f$\alpha\f$ based on order statistics + \f$X_{1:n} \leq X_{2:n} \leq\dots\leq X_{n:n}\f$ of weighted samples are given by \f$X_{\lambda:n}\f$ (left tail) + and \f$X_{\rho:n}\f$ (right tail), where + + \f[ + \lambda = \inf\left\{ l \left| \frac{1}{\bar{w}_n}\sum_{i=1}^{l} w_i \geq \alpha \right. \right\} + \f] + + and + + \f[ + \rho = \sup\left\{ r \left| \frac{1}{\bar{w}_n}\sum_{i=r}^{n} w_i \geq (1 - \alpha) \right. \right\}, + \f] + + \f$n\f$ being the number of samples and \f$\bar{w}_n\f$ the sum of all weights. + + @param quantile_probability + */ + template<typename Sample, typename Weight, typename LeftRight> + struct weighted_tail_quantile_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Weight, std::size_t>::result_type float_type; + // for boost::result_of + typedef Sample result_type; + + weighted_tail_quantile_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + float_type threshold = sum_of_weights(args) + * ( ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ); + + std::size_t n = 0; + Weight sum = Weight(0); + + while (sum < threshold) + { + if (n < static_cast<std::size_t>(tail_weights(args).size())) + { + sum += *(tail_weights(args).begin() + n); + n++; + } + else + { + if (std::numeric_limits<result_type>::has_quiet_NaN) + { + return std::numeric_limits<result_type>::quiet_NaN(); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + return Sample(0); + } + } + } + + // Note that the cached samples of the left are sorted in ascending order, + // whereas the samples of the right tail are sorted in descending order + return *(boost::begin(tail(args)) + n - 1); + } + }; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_tail_quantile<> +// +namespace tag +{ + template<typename LeftRight> + struct weighted_tail_quantile + : depends_on<sum_of_weights, tail_weights<LeftRight> > + { + /// INTERNAL ONLY + typedef accumulators::impl::weighted_tail_quantile_impl<mpl::_1, mpl::_2, LeftRight> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_tail_quantile +// +namespace extract +{ + extractor<tag::quantile> const weighted_tail_quantile = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_tail_quantile) +} + +using extract::weighted_tail_quantile; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_tail_variate_means.hpp b/boost/boost/accumulators/statistics/weighted_tail_variate_means.hpp new file mode 100644 index 0000000..2c90783 --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_tail_variate_means.hpp
@@ -0,0 +1,242 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_tail_variate_means.hpp +// +// Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_TAIL_VARIATE_MEANS_HPP_DE_01_01_2006 + +#include <numeric> +#include <vector> +#include <limits> +#include <functional> +#include <sstream> +#include <stdexcept> +#include <boost/throw_exception.hpp> +#include <boost/parameter/keyword.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/accumulators/numeric/functional.hpp> +#include <boost/accumulators/framework/accumulator_base.hpp> +#include <boost/accumulators/framework/extractor.hpp> +#include <boost/accumulators/framework/parameters/sample.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/tail.hpp> +#include <boost/accumulators/statistics/tail_variate.hpp> +#include <boost/accumulators/statistics/tail_variate_means.hpp> +#include <boost/accumulators/statistics/weighted_tail_mean.hpp> +#include <boost/accumulators/statistics/parameters/quantile_probability.hpp> + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +#endif + +namespace boost +{ + // for _BinaryOperatrion2 in std::inner_product below + // multiplies two values and promotes the result to double + namespace numeric { namespace functional + { + /////////////////////////////////////////////////////////////////////////////// + // numeric::functional::multiply_and_promote_to_double + template<typename T, typename U> + struct multiply_and_promote_to_double + : multiplies<T, double const> + { + }; + }} +} + +namespace boost { namespace accumulators +{ + +namespace impl +{ + /** + @brief Estimation of the absolute and relative weighted tail variate means (for both left and right tails) + + For all \f$j\f$-th variates associated to the + + \f[ + \lambda = \inf\left\{ l \left| \frac{1}{\bar{w}_n}\sum_{i=1}^{l} w_i \geq \alpha \right. \right\} + \f] + + smallest samples (left tail) or the weighted mean of the + + \f[ + n + 1 - \rho = n + 1 - \sup\left\{ r \left| \frac{1}{\bar{w}_n}\sum_{i=r}^{n} w_i \geq (1 - \alpha) \right. \right\} + \f] + + largest samples (right tail), the absolute weighted tail means \f$\widehat{ATM}_{n,\alpha}(X, j)\f$ + are computed and returned as an iterator range. Alternatively, the relative weighted tail means + \f$\widehat{RTM}_{n,\alpha}(X, j)\f$ are returned, which are the absolute weighted tail means + normalized with the weighted (non-coherent) sample tail mean \f$\widehat{NCTM}_{n,\alpha}(X)\f$. + + \f[ + \widehat{ATM}_{n,\alpha}^{\mathrm{right}}(X, j) = + \frac{1}{\sum_{i=\rho}^n w_i} + \sum_{i=\rho}^n w_i \xi_{j,i} + \f] + + \f[ + \widehat{ATM}_{n,\alpha}^{\mathrm{left}}(X, j) = + \frac{1}{\sum_{i=1}^{\lambda}} + \sum_{i=1}^{\lambda} w_i \xi_{j,i} + \f] + + \f[ + \widehat{RTM}_{n,\alpha}^{\mathrm{right}}(X, j) = + \frac{\sum_{i=\rho}^n w_i \xi_{j,i}} + {\sum_{i=\rho}^n w_i \widehat{NCTM}_{n,\alpha}^{\mathrm{right}}(X)} + \f] + + \f[ + \widehat{RTM}_{n,\alpha}^{\mathrm{left}}(X, j) = + \frac{\sum_{i=1}^{\lambda} w_i \xi_{j,i}} + {\sum_{i=1}^{\lambda} w_i \widehat{NCTM}_{n,\alpha}^{\mathrm{left}}(X)} + \f] + */ + + /////////////////////////////////////////////////////////////////////////////// + // weighted_tail_variate_means_impl + // by default: absolute weighted_tail_variate_means + template<typename Sample, typename Weight, typename Impl, typename LeftRight, typename VariateType> + struct weighted_tail_variate_means_impl + : accumulator_base + { + typedef typename numeric::functional::fdiv<Weight, Weight>::result_type float_type; + typedef typename numeric::functional::fdiv<typename numeric::functional::multiplies<VariateType, Weight>::result_type, Weight>::result_type array_type; + // for boost::result_of + typedef iterator_range<typename array_type::iterator> result_type; + + weighted_tail_variate_means_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + float_type threshold = sum_of_weights(args) + * ( ( is_same<LeftRight, left>::value ) ? args[quantile_probability] : 1. - args[quantile_probability] ); + + std::size_t n = 0; + Weight sum = Weight(0); + + while (sum < threshold) + { + if (n < static_cast<std::size_t>(tail_weights(args).size())) + { + sum += *(tail_weights(args).begin() + n); + n++; + } + else + { + if (std::numeric_limits<float_type>::has_quiet_NaN) + { + std::fill( + this->tail_means_.begin() + , this->tail_means_.end() + , std::numeric_limits<float_type>::quiet_NaN() + ); + } + else + { + std::ostringstream msg; + msg << "index n = " << n << " is not in valid range [0, " << tail(args).size() << ")"; + boost::throw_exception(std::runtime_error(msg.str())); + } + } + } + + std::size_t num_variates = tail_variate(args).begin()->size(); + + this->tail_means_.clear(); + this->tail_means_.resize(num_variates, Sample(0)); + + this->tail_means_ = std::inner_product( + tail_variate(args).begin() + , tail_variate(args).begin() + n + , tail_weights(args).begin() + , this->tail_means_ + , numeric::functional::plus<array_type const, array_type const>() + , numeric::functional::multiply_and_promote_to_double<VariateType const, Weight const>() + ); + + float_type factor = sum * ( (is_same<Impl, relative>::value) ? non_coherent_weighted_tail_mean(args) : 1. ); + + std::transform( + this->tail_means_.begin() + , this->tail_means_.end() + , this->tail_means_.begin() + , std::bind2nd(numeric::functional::divides<typename array_type::value_type const, float_type const>(), factor) + ); + + return make_iterator_range(this->tail_means_); + } + + private: + + mutable array_type tail_means_; + + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::absolute_weighted_tail_variate_means +// tag::relative_weighted_tail_variate_means +// +namespace tag +{ + template<typename LeftRight, typename VariateType, typename VariateTag> + struct absolute_weighted_tail_variate_means + : depends_on<non_coherent_weighted_tail_mean<LeftRight>, tail_variate<VariateType, VariateTag, LeftRight>, tail_weights<LeftRight> > + { + typedef accumulators::impl::weighted_tail_variate_means_impl<mpl::_1, mpl::_2, absolute, LeftRight, VariateType> impl; + }; + template<typename LeftRight, typename VariateType, typename VariateTag> + struct relative_weighted_tail_variate_means + : depends_on<non_coherent_weighted_tail_mean<LeftRight>, tail_variate<VariateType, VariateTag, LeftRight>, tail_weights<LeftRight> > + { + typedef accumulators::impl::weighted_tail_variate_means_impl<mpl::_1, mpl::_2, relative, LeftRight, VariateType> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_tail_variate_means +// extract::relative_weighted_tail_variate_means +// +namespace extract +{ + extractor<tag::abstract_absolute_tail_variate_means> const weighted_tail_variate_means = {}; + extractor<tag::abstract_relative_tail_variate_means> const relative_weighted_tail_variate_means = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_tail_variate_means) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(relative_weighted_tail_variate_means) +} + +using extract::weighted_tail_variate_means; +using extract::relative_weighted_tail_variate_means; + +// weighted_tail_variate_means<LeftRight, VariateType, VariateTag>(absolute) -> absolute_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> +template<typename LeftRight, typename VariateType, typename VariateTag> +struct as_feature<tag::weighted_tail_variate_means<LeftRight, VariateType, VariateTag>(absolute)> +{ + typedef tag::absolute_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> type; +}; + +// weighted_tail_variate_means<LeftRight, VariateType, VariateTag>(relative) -> relative_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> +template<typename LeftRight, typename VariateType, typename VariateTag> +struct as_feature<tag::weighted_tail_variate_means<LeftRight, VariateType, VariateTag>(relative)> +{ + typedef tag::relative_weighted_tail_variate_means<LeftRight, VariateType, VariateTag> type; +}; + +}} // namespace boost::accumulators + +#ifdef _MSC_VER +# pragma warning(pop) +#endif + +#endif
diff --git a/boost/boost/accumulators/statistics/weighted_variance.hpp b/boost/boost/accumulators/statistics/weighted_variance.hpp new file mode 100644 index 0000000..bc199af --- /dev/null +++ b/boost/boost/accumulators/statistics/weighted_variance.hpp
@@ -0,0 +1,186 @@ +/////////////////////////////////////////////////////////////////////////////// +// weighted_variance.hpp +// +// Copyright 2005 Daniel Egloff, Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_VARIANCE_HPP_EAN_28_10_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WEIGHTED_VARIANCE_HPP_EAN_28_10_2005 + +#include <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/framework/depends_on.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/count.hpp> +#include <boost/accumulators/statistics/variance.hpp> +#include <boost/accumulators/statistics/weighted_sum.hpp> +#include <boost/accumulators/statistics/weighted_mean.hpp> +#include <boost/accumulators/statistics/weighted_moment.hpp> + +namespace boost { namespace accumulators +{ + +namespace impl +{ + //! Lazy calculation of variance of weighted samples. + /*! + The default implementation of the variance of weighted samples is based on the second moment + \f$\widehat{m}_n^{(2)}\f$ (weighted_moment<2>) and the mean\f$ \hat{\mu}_n\f$ (weighted_mean): + \f[ + \hat{\sigma}_n^2 = \widehat{m}_n^{(2)}-\hat{\mu}_n^2, + \f] + where \f$n\f$ is the number of samples. + */ + template<typename Sample, typename Weight, typename MeanFeature> + struct lazy_weighted_variance_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::fdiv<weighted_sample, Weight>::result_type result_type; + + lazy_weighted_variance_impl(dont_care) {} + + template<typename Args> + result_type result(Args const &args) const + { + extractor<MeanFeature> const some_mean = {}; + result_type tmp = some_mean(args); + return accumulators::weighted_moment<2>(args) - tmp * tmp; + } + }; + + //! Iterative calculation of variance of weighted samples. + /*! + Iterative calculation of variance of weighted samples: + \f[ + \hat{\sigma}_n^2 = + \frac{\bar{w}_n - w_n}{\bar{w}_n}\hat{\sigma}_{n - 1}^2 + + \frac{w_n}{\bar{w}_n - w_n}\left(X_n - \hat{\mu}_n\right)^2 + ,\quad n\ge2,\quad\hat{\sigma}_0^2 = 0. + \f] + where \f$\bar{w}_n\f$ is the sum of the \f$n\f$ weights \f$w_i\f$ and \f$\hat{\mu}_n\f$ + the estimate of the mean of the weighted samples. Note that the sample variance is not defined for + \f$n <= 1\f$. + */ + template<typename Sample, typename Weight, typename MeanFeature, typename Tag> + struct weighted_variance_impl + : accumulator_base + { + typedef typename numeric::functional::multiplies<Sample, Weight>::result_type weighted_sample; + // for boost::result_of + typedef typename numeric::functional::fdiv<weighted_sample, Weight>::result_type result_type; + + template<typename Args> + weighted_variance_impl(Args const &args) + : weighted_variance(numeric::fdiv(args[sample | Sample()], numeric::one<Weight>::value)) + { + } + + template<typename Args> + void operator ()(Args const &args) + { + std::size_t cnt = count(args); + + if(cnt > 1) + { + extractor<MeanFeature> const some_mean = {}; + + result_type tmp = args[parameter::keyword<Tag>::get()] - some_mean(args); + + this->weighted_variance = + numeric::fdiv(this->weighted_variance * (sum_of_weights(args) - args[weight]), sum_of_weights(args)) + + numeric::fdiv(tmp * tmp * args[weight], sum_of_weights(args) - args[weight] ); + } + } + + result_type result(dont_care) const + { + return this->weighted_variance; + } + + private: + result_type weighted_variance; + }; + +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// tag::weighted_variance +// tag::immediate_weighted_variance +// +namespace tag +{ + struct lazy_weighted_variance + : depends_on<weighted_moment<2>, weighted_mean> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::lazy_weighted_variance_impl<mpl::_1, mpl::_2, weighted_mean> impl; + }; + + struct weighted_variance + : depends_on<count, immediate_weighted_mean> + { + /// INTERNAL ONLY + /// + typedef accumulators::impl::weighted_variance_impl<mpl::_1, mpl::_2, immediate_weighted_mean, sample> impl; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// extract::weighted_variance +// extract::immediate_weighted_variance +// +namespace extract +{ + extractor<tag::lazy_weighted_variance> const lazy_weighted_variance = {}; + extractor<tag::weighted_variance> const weighted_variance = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(lazy_weighted_variance) + BOOST_ACCUMULATORS_IGNORE_GLOBAL(weighted_variance) +} + +using extract::lazy_weighted_variance; +using extract::weighted_variance; + +// weighted_variance(lazy) -> lazy_weighted_variance +template<> +struct as_feature<tag::weighted_variance(lazy)> +{ + typedef tag::lazy_weighted_variance type; +}; + +// weighted_variance(immediate) -> weighted_variance +template<> +struct as_feature<tag::weighted_variance(immediate)> +{ + typedef tag::weighted_variance type; +}; + +//////////////////////////////////////////////////////////////////////////// +//// droppable_accumulator<weighted_variance_impl> +//// need to specialize droppable lazy weighted_variance to cache the result at the +//// point the accumulator is dropped. +///// INTERNAL ONLY +///// +//template<typename Sample, typename Weight, typename MeanFeature> +//struct droppable_accumulator<impl::weighted_variance_impl<Sample, Weight, MeanFeature> > +// : droppable_accumulator_base< +// with_cached_result<impl::weighted_variance_impl<Sample, Weight, MeanFeature> > +// > +//{ +// template<typename Args> +// droppable_accumulator(Args const &args) +// : droppable_accumulator::base(args) +// { +// } +//}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics/with_error.hpp b/boost/boost/accumulators/statistics/with_error.hpp new file mode 100644 index 0000000..adafc8e --- /dev/null +++ b/boost/boost/accumulators/statistics/with_error.hpp
@@ -0,0 +1,44 @@ +/////////////////////////////////////////////////////////////////////////////// +// with_error.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_WITH_ERROR_HPP_EAN_01_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_WITH_ERROR_HPP_EAN_01_11_2005 + +#include <boost/preprocessor/repetition/enum_params.hpp> +#include <boost/mpl/vector.hpp> +#include <boost/mpl/transform_view.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/accumulators/statistics_fwd.hpp> +#include <boost/accumulators/statistics/error_of.hpp> + +namespace boost { namespace accumulators +{ + +namespace detail +{ + template<typename Feature> + struct error_of_tag + { + typedef tag::error_of<Feature> type; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// with_error +// +template<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature)> +struct with_error + : mpl::transform_view< + mpl::vector<BOOST_PP_ENUM_PARAMS(BOOST_ACCUMULATORS_MAX_FEATURES, Feature)> + , detail::error_of_tag<mpl::_1> + > +{ +}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/accumulators/statistics_fwd.hpp b/boost/boost/accumulators/statistics_fwd.hpp new file mode 100644 index 0000000..61904f3 --- /dev/null +++ b/boost/boost/accumulators/statistics_fwd.hpp
@@ -0,0 +1,432 @@ +/////////////////////////////////////////////////////////////////////////////// +// statistics_fwd.hpp +// +// Copyright 2005 Eric Niebler. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ACCUMULATORS_STATISTICS_STATISTICS_FWD_HPP_EAN_23_11_2005 +#define BOOST_ACCUMULATORS_STATISTICS_STATISTICS_FWD_HPP_EAN_23_11_2005 + +#include <boost/mpl/apply_fwd.hpp> // for mpl::na +#include <boost/mpl/print.hpp> +#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp> +#include <boost/accumulators/accumulators_fwd.hpp> +#include <boost/accumulators/framework/depends_on.hpp> +#include <boost/accumulators/framework/extractor.hpp> + +namespace boost { namespace accumulators +{ + +/////////////////////////////////////////////////////////////////////////////// +// base struct and base extractor for quantiles +namespace tag +{ + struct quantile + : depends_on<> + { + typedef mpl::print<class ____MISSING_SPECIFIC_QUANTILE_FEATURE_IN_ACCUMULATOR_SET____ > impl; + }; +} +namespace extract +{ + extractor<tag::quantile> const quantile = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(quantile) +} +using extract::quantile; + +/////////////////////////////////////////////////////////////////////////////// +// base struct and base extractor for *coherent* tail means +namespace tag +{ + struct tail_mean + : depends_on<> + { + typedef mpl::print<class ____MISSING_SPECIFIC_TAIL_MEAN_FEATURE_IN_ACCUMULATOR_SET____ > impl; + }; +} +namespace extract +{ + extractor<tag::tail_mean> const tail_mean = {}; + + BOOST_ACCUMULATORS_IGNORE_GLOBAL(tail_mean) +} +using extract::tail_mean; + +namespace tag +{ + /////////////////////////////////////////////////////////////////////////////// + // Variates tags + struct weights; + struct covariate1; + struct covariate2; + + /////////////////////////////////////////////////////////////////////////////// + // Statistic tags + struct count; + template<typename VariateType, typename VariateTag> + struct covariance; + struct density; + template<typename Feature> + struct error_of; + struct extended_p_square; + struct extended_p_square_quantile; + struct extended_p_square_quantile_quadratic; + struct kurtosis; + struct max; + struct mean; + struct immediate_mean; + struct mean_of_weights; + struct immediate_mean_of_weights; + template<typename VariateType, typename VariateTag> + struct mean_of_variates; + template<typename VariateType, typename VariateTag> + struct immediate_mean_of_variates; + struct median; + struct with_density_median; + struct with_p_square_cumulative_distribution_median; + struct min; + template<int N> + struct moment; + template<typename LeftRight> + struct peaks_over_threshold; + template<typename LeftRight> + struct peaks_over_threshold_prob; + template<typename LeftRight> + struct pot_tail_mean; + template<typename LeftRight> + struct pot_tail_mean_prob; + template<typename LeftRight> + struct pot_quantile; + template<typename LeftRight> + struct pot_quantile_prob; + struct p_square_cumulative_distribution; + struct p_square_quantile; + struct p_square_quantile_for_median; + struct skewness; + struct sum; + struct sum_of_weights; + template<typename VariateType, typename VariateTag> + struct sum_of_variates; + struct sum_kahan; + struct sum_of_weights_kahan; + template<typename VariateType, typename VariateTag> + struct sum_of_variates_kahan; + template<typename LeftRight> + struct tail; + template<typename LeftRight> + struct coherent_tail_mean; + template<typename LeftRight> + struct non_coherent_tail_mean; + template<typename LeftRight> + struct tail_quantile; + template<typename VariateType, typename VariateTag, typename LeftRight> + struct tail_variate; + template<typename LeftRight> + struct tail_weights; + template<typename VariateType, typename VariateTag, typename LeftRight> + struct right_tail_variate; + template<typename VariateType, typename VariateTag, typename LeftRight> + struct left_tail_variate; + template<typename LeftRight, typename VariateType, typename VariateTag> + struct tail_variate_means; + template<typename LeftRight, typename VariateType, typename VariateTag> + struct absolute_tail_variate_means; + template<typename LeftRight, typename VariateType, typename VariateTag> + struct relative_tail_variate_means; + struct lazy_variance; + struct variance; + template<typename VariateType, typename VariateTag> + struct weighted_covariance; + struct weighted_density; + struct weighted_kurtosis; + struct weighted_mean; + struct immediate_weighted_mean; + template<typename VariateType, typename VariateTag> + struct weighted_mean_of_variates; + template<typename VariateType, typename VariateTag> + struct immediate_weighted_mean_of_variates; + struct weighted_median; + struct with_density_weighted_median; + struct with_p_square_cumulative_distribution_weighted_median; + struct weighted_extended_p_square; + struct weighted_extended_p_square_quantile; + struct weighted_extended_p_square_quantile_quadratic; + template<int N> + struct weighted_moment; + template<typename LeftRight> + struct weighted_peaks_over_threshold; + template<typename LeftRight> + struct weighted_peaks_over_threshold_prob; + template<typename LeftRight> + struct weighted_pot_quantile; + template<typename LeftRight> + struct weighted_pot_quantile_prob; + template<typename LeftRight> + struct weighted_pot_tail_mean; + template<typename LeftRight> + struct weighted_pot_tail_mean_prob; + struct weighted_p_square_cumulative_distribution; + struct weighted_p_square_quantile; + struct weighted_p_square_quantile_for_median; + struct weighted_skewness; + template<typename LeftRight> + struct weighted_tail_quantile; + template<typename LeftRight> + struct non_coherent_weighted_tail_mean; + template<typename LeftRight> + struct weighted_tail_quantile; + template<typename LeftRight, typename VariateType, typename VariateTag> + struct weighted_tail_variate_means; + template<typename LeftRight, typename VariateType, typename VariateTag> + struct absolute_weighted_tail_variate_means; + template<typename LeftRight, typename VariateType, typename VariateTag> + struct relative_weighted_tail_variate_means; + struct lazy_weighted_variance; + struct weighted_variance; + struct weighted_sum; + template<typename VariateType, typename VariateTag> + struct weighted_sum_of_variates; + struct rolling_window_plus1; + struct rolling_window; + struct rolling_sum; + struct rolling_count; + struct rolling_mean; +} // namespace tag + +namespace impl +{ + /////////////////////////////////////////////////////////////////////////////// + // Statistics impls + struct count_impl; + + template<typename Sample, typename VariateType, typename VariateTag> + struct covariance_impl; + + template<typename Sample> + struct density_impl; + + template<typename Sample, typename Feature> + struct error_of_impl; + + template<typename Sample, typename Variance> + struct error_of_mean_impl; + + template<typename Sample> + struct extended_p_square_impl; + + template<typename Sample, typename Impl1, typename Impl2> + struct extended_p_square_quantile_impl; + + template<typename Sample> + struct kurtosis_impl; + + template<typename Sample> + struct max_impl; + + template<typename Sample> + struct median_impl; + + template<typename Sample> + struct with_density_median_impl; + + template<typename Sample> + struct with_p_square_cumulative_distribution_median_impl; + + template<typename Sample> + struct min_impl; + + template<typename Sample, typename SumFeature = tag::sum> + struct mean_impl; + + template<typename Sample, typename Tag = tag::sample> + struct immediate_mean_impl; + + template<typename N, typename Sample> + struct moment_impl; + + template<typename Sample, typename LeftRight> + struct peaks_over_threshold_prob_impl; + + template<typename Sample, typename Impl, typename LeftRight> + struct pot_quantile_impl; + + template<typename Sample, typename Impl, typename LeftRight> + struct pot_tail_mean_impl; + + template<typename Sample> + struct p_square_cumulative_distribution_impl; + + template<typename Sample, typename Impl> + struct p_square_quantile_impl; + + template<typename Sample> + struct skewness_impl; + + template<typename Sample, typename Tag = tag::sample> + struct sum_impl; + + template<typename Sample, typename Tag> + struct sum_kahan_impl; + + template<typename Sample, typename LeftRight> + struct tail_impl; + + template<typename Sample, typename LeftRight> + struct coherent_tail_mean_impl; + + template<typename Sample, typename LeftRight> + struct non_coherent_tail_mean_impl; + + template<typename Sample, typename LeftRight> + struct tail_quantile_impl; + + template<typename VariateType, typename VariateTag, typename LeftRight> + struct tail_variate_impl; + + template<typename Sample, typename Impl, typename LeftRight, typename VariateTag> + struct tail_variate_means_impl; + + template<typename Sample, typename MeanFeature> + struct lazy_variance_impl; + + template<typename Sample, typename MeanFeature, typename Tag> + struct variance_impl; + + template<typename Sample, typename Weight, typename VariateType, typename VariateTag> + struct weighted_covariance_impl; + + template<typename Sample, typename Weight> + struct weighted_density_impl; + + template<typename Sample, typename Weight> + struct weighted_kurtosis_impl; + + template<typename Sample> + struct weighted_median_impl; + + template<typename Sample> + struct with_density_weighted_median_impl; + + template<typename Sample, typename Weight> + struct with_p_square_cumulative_distribution_weighted_median_impl; + + template<typename Sample, typename Weight, typename Tag> + struct weighted_mean_impl; + + template<typename Sample, typename Weight, typename Tag> + struct immediate_weighted_mean_impl; + + template<typename Sample, typename Weight, typename LeftRight> + struct weighted_peaks_over_threshold_impl; + + template<typename Sample, typename Weight, typename LeftRight> + struct weighted_peaks_over_threshold_prob_impl; + + template<typename Sample, typename Weight> + struct with_p_square_cumulative_distribution_weighted_median_impl; + + template<typename Sample, typename Weight> + struct weighted_extended_p_square_impl; + + template<typename N, typename Sample, typename Weight> + struct weighted_moment_impl; + + template<typename Sample, typename Weight> + struct weighted_p_square_cumulative_distribution_impl; + + template<typename Sample, typename Weight, typename Impl> + struct weighted_p_square_quantile_impl; + + template<typename Sample, typename Weight> + struct weighted_skewness_impl; + + template<typename Sample, typename Weight, typename Tag> + struct weighted_sum_impl; + + template<typename Sample, typename Weight, typename Tag> + struct weighted_sum_kahan_impl; + + template<typename Sample, typename Weight, typename LeftRight> + struct non_coherent_weighted_tail_mean_impl; + + template<typename Sample, typename Weight, typename LeftRight> + struct weighted_tail_quantile_impl; + + template<typename Sample, typename Weight, typename Impl, typename LeftRight, typename VariateType> + struct weighted_tail_variate_means_impl; + + template<typename Sample, typename Weight, typename MeanFeature> + struct lazy_weighted_variance_impl; + + template<typename Sample, typename Weight, typename MeanFeature, typename Tag> + struct weighted_variance_impl; + + template<typename Sample> + struct rolling_window_plus1_impl; + + template<typename Sample> + struct rolling_window_impl; + + template<typename Sample> + struct rolling_sum_impl; + + template<typename Sample> + struct rolling_count_impl; + + template<typename Sample> + struct rolling_mean_impl; +} // namespace impl + +/////////////////////////////////////////////////////////////////////////////// +// stats +// A more descriptive name for an MPL sequence of statistics. +template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature, mpl::na)> +struct stats; + +template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_ACCUMULATORS_MAX_FEATURES, typename Feature, mpl::na)> +struct with_error; + +// modifiers for the mean and variance stats +struct lazy {}; +struct immediate {}; + +// modifiers for the variance stat +// struct fast {}; +// struct accurate {}; + +// modifiers for order +struct right {}; +struct left {}; +// typedef right default_order_tag_type; + +// modifiers for the tail_variate_means stat +struct absolute {}; +struct relative {}; + +// modifiers for median and weighted_median stats +struct with_density {}; +struct with_p_square_cumulative_distribution {}; +struct with_p_square_quantile {}; + +// modifiers for peaks_over_threshold stat +struct with_threshold_value {}; +struct with_threshold_probability {}; + +// modifiers for extended_p_square_quantile and weighted_extended_p_square_quantile stats +struct weighted {}; +struct unweighted {}; +struct linear {}; +struct quadratic {}; + +// modifiers for p_square_quantile +struct regular {}; +struct for_median {}; + +// modifier for sum_kahan, sum_of_weights_kahan, sum_of_variates_kahan, weighted_sum_kahan +struct kahan {}; + +}} // namespace boost::accumulators + +#endif
diff --git a/boost/boost/algorithm/algorithm.hpp b/boost/boost/algorithm/algorithm.hpp new file mode 100644 index 0000000..0cf6c45 --- /dev/null +++ b/boost/boost/algorithm/algorithm.hpp
@@ -0,0 +1,86 @@ +/* + Copyright (c) Marshall Clow 2014. + + Distributed under the 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: + 2 Dec 2014 mtc First version; power + +*/ + +/// \file algorithm.hpp +/// \brief Misc Algorithms +/// \author Marshall Clow +/// + +#ifndef BOOST_ALGORITHM_HPP +#define BOOST_ALGORITHM_HPP + +#include <boost/utility/enable_if.hpp> // for boost::disable_if +#include <boost/type_traits/is_integral.hpp> + +namespace boost { namespace algorithm { + +template <typename T> +T identity_operation ( std::multiplies<T> ) { return T(1); } + +template <typename T> +T identity_operation ( std::plus<T> ) { return T(0); } + + +/// \fn power ( T x, Integer n ) +/// \return the value "x" raised to the power "n" +/// +/// \param x The value to be exponentiated +/// \param n The exponent (must be >= 0) +/// +// \remark Taken from Knuth, The Art of Computer Programming, Volume 2: +// Seminumerical Algorithms, Section 4.6.3 +template <typename T, typename Integer> +typename boost::enable_if<boost::is_integral<Integer>, T>::type +power (T x, Integer n) { + T y = 1; // Should be "T y{1};" + if (n == 0) return y; + while (true) { + if (n % 2 == 1) { + y = x * y; + if (n == 1) + return y; + } + n = n / 2; + x = x * x; + } + return y; + } + +/// \fn power ( T x, Integer n, Operation op ) +/// \return the value "x" raised to the power "n" +/// using the operaton "op". +/// +/// \param x The value to be exponentiated +/// \param n The exponent (must be >= 0) +/// \param op The operation used +/// +// \remark Taken from Knuth, The Art of Computer Programming, Volume 2: +// Seminumerical Algorithms, Section 4.6.3 +template <typename T, typename Integer, typename Operation> +typename boost::enable_if<boost::is_integral<Integer>, T>::type +power (T x, Integer n, Operation op) { + T y = identity_operation(op); + if (n == 0) return y; + while (true) { + if (n % 2 == 1) { + y = op(x, y); + if (n == 1) + return y; + } + n = n / 2; + x = op(x, x); + } + return y; + } + +}} + +#endif // BOOST_ALGORITHM_HPP
diff --git a/boost/boost/algorithm/clamp.hpp b/boost/boost/algorithm/clamp.hpp new file mode 100644 index 0000000..7bfa47e --- /dev/null +++ b/boost/boost/algorithm/clamp.hpp
@@ -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 const & lo, +/// std::iterator_traits<InputIterator>::value_type const & 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 const & lo, + typename std::iterator_traits<InputIterator>::value_type const & 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 const & lo, +/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & 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 const & lo, + typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & 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 const & lo, +/// std::iterator_traits<InputIterator>::value_type const & 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 const & lo, + typename std::iterator_traits<InputIterator>::value_type const & 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 const & lo, +/// typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & 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 const & lo, + typename std::iterator_traits<typename boost::range_iterator<const Range>::type>::value_type const & hi, + Pred p ) + { + return clamp_range ( boost::begin ( r ), boost::end ( r ), out, lo, hi, p ); + } + + +}} + +#endif // BOOST_ALGORITHM_CLAMP_HPP
diff --git a/boost/boost/algorithm/cxx11/all_of.hpp b/boost/boost/algorithm/cxx11/all_of.hpp new file mode 100644 index 0000000..39cab39 --- /dev/null +++ b/boost/boost/algorithm/cxx11/all_of.hpp
@@ -0,0 +1,86 @@ +/* + 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 { + +/// \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; +} + +/// \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
diff --git a/boost/boost/algorithm/cxx11/any_of.hpp b/boost/boost/algorithm/cxx11/any_of.hpp new file mode 100644 index 0000000..cf69348 --- /dev/null +++ b/boost/boost/algorithm/cxx11/any_of.hpp
@@ -0,0 +1,85 @@ +/* + 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 { + +/// \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; +} + +/// \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
diff --git a/boost/boost/algorithm/cxx11/copy_if.hpp b/boost/boost/algorithm/cxx11/copy_if.hpp new file mode 100644 index 0000000..d869caf --- /dev/null +++ b/boost/boost/algorithm/cxx11/copy_if.hpp
@@ -0,0 +1,131 @@ +/* + 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 { + +/// \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; +} + +/// \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 input and output iterators +/// +/// \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> +std::pair<InputIterator, OutputIterator> +copy_while ( InputIterator first, InputIterator last, OutputIterator result, Predicate p ) +{ + for ( ; first != last && p(*first); ++first ) + *result++ = *first; + return std::make_pair(first, 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 input and output iterators +/// +/// \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> +std::pair<typename boost::range_iterator<const Range>::type, 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> +std::pair<InputIterator, OutputIterator> +copy_until ( InputIterator first, InputIterator last, OutputIterator result, Predicate p ) +{ + for ( ; first != last && !p(*first); ++first ) + *result++ = *first; + return std::make_pair(first, 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> +std::pair<typename boost::range_iterator<const Range>::type, 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
diff --git a/boost/boost/algorithm/cxx11/copy_n.hpp b/boost/boost/algorithm/cxx11/copy_n.hpp new file mode 100644 index 0000000..ebfe889 --- /dev/null +++ b/boost/boost/algorithm/cxx11/copy_n.hpp
@@ -0,0 +1,39 @@ +/* + 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 { + +/// \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; +} +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_COPY_IF_HPP
diff --git a/boost/boost/algorithm/cxx11/find_if_not.hpp b/boost/boost/algorithm/cxx11/find_if_not.hpp new file mode 100644 index 0000000..414697c --- /dev/null +++ b/boost/boost/algorithm/cxx11/find_if_not.hpp
@@ -0,0 +1,55 @@ +/* + 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 { + +/// \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; +} + +/// \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
diff --git a/boost/boost/algorithm/cxx11/iota.hpp b/boost/boost/algorithm/cxx11/iota.hpp new file mode 100644 index 0000000..2e638ec --- /dev/null +++ b/boost/boost/algorithm/cxx11/iota.hpp
@@ -0,0 +1,69 @@ +/* + 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 { + +/// \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; +} + +/// \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 ) +{ + for ( ; n > 0; --n, ++value ) + *out++ = value; + + return out; +} + +}} + +#endif // BOOST_ALGORITHM_IOTA_HPP
diff --git a/boost/boost/algorithm/cxx11/is_partitioned.hpp b/boost/boost/algorithm/cxx11/is_partitioned.hpp new file mode 100644 index 0000000..cdabd97 --- /dev/null +++ b/boost/boost/algorithm/cxx11/is_partitioned.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 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 { + +/// \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; +} + +/// \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
diff --git a/boost/boost/algorithm/cxx11/is_permutation.hpp b/boost/boost/algorithm/cxx11/is_permutation.hpp new file mode 100644 index 0000000..ec902dc --- /dev/null +++ b/boost/boost/algorithm/cxx11/is_permutation.hpp
@@ -0,0 +1,189 @@ +/* + 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_PERMUTATION11_HPP +#define BOOST_ALGORITHM_IS_PERMUTATION11_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> + +namespace boost { namespace algorithm { + +/// \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_; + }; + +// Preconditions: +// 1. The sequences are the same length +// 2. Any common elements on the front have been removed (not necessary for correctness, just for performance) + template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > + bool is_permutation_inner ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate p ) { + // 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 ) { + 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; + } + + template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> + bool is_permutation_tag ( ForwardIterator1 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2, + BinaryPredicate p, + std::forward_iterator_tag, std::forward_iterator_tag ) { + + // Skip the common prefix (if any) + while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) { + ++first1; + ++first2; + } + if ( first1 != last1 && first2 != last2 ) + return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, + std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> ()); + return first1 == last1 && first2 == last2; + } + + template <class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate> + bool is_permutation_tag ( RandomAccessIterator1 first1, RandomAccessIterator1 last1, + RandomAccessIterator2 first2, RandomAccessIterator2 last2, + BinaryPredicate p, + std::random_access_iterator_tag, std::random_access_iterator_tag ) { + // Cheap check + if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 )) + return false; + // Skip the common prefix (if any) + while ( first1 != last1 && first2 != last2 && p ( *first1, *first2 )) { + ++first1; + ++first2; + } + + if ( first1 != last1 && first2 != last2 ) + return is_permutation_inner (first1, last1, first2, last2, p); + return first1 == last1 && first2 == last2; + } + +} +/// \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 first1 The start of the input sequence +/// \param last1 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::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)); + return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, p ); + } + + 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 first1 The start of the input sequence +/// \param last2 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 first1, ForwardIterator1 last1, 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? +// Skip the common prefix (if any) + std::pair<ForwardIterator1, ForwardIterator2> eq = std::mismatch (first1, last1, first2 ); + first1 = eq.first; + first2 = eq.second; + if ( first1 != last1 ) { + // Create last2 + ForwardIterator2 last2 = first2; + std::advance ( last2, std::distance (first1, last1)); + return boost::algorithm::detail::is_permutation_inner ( first1, last1, first2, last2, + std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> ()); + } + return true; +} + + +/// \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_PERMUTATION11_HPP
diff --git a/boost/boost/algorithm/cxx11/is_sorted.hpp b/boost/boost/algorithm/cxx11/is_sorted.hpp new file mode 100644 index 0000000..f6062da --- /dev/null +++ b/boost/boost/algorithm/cxx11/is_sorted.hpp
@@ -0,0 +1,281 @@ +// 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 { + +/// \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; + } + +/// +/// -- 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
diff --git a/boost/boost/algorithm/cxx11/none_of.hpp b/boost/boost/algorithm/cxx11/none_of.hpp new file mode 100644 index 0000000..67be3d1 --- /dev/null +++ b/boost/boost/algorithm/cxx11/none_of.hpp
@@ -0,0 +1,83 @@ +/* + 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 { + +/// \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; +} + +/// \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
diff --git a/boost/boost/algorithm/cxx11/one_of.hpp b/boost/boost/algorithm/cxx11/one_of.hpp new file mode 100644 index 0000000..b6e8c77 --- /dev/null +++ b/boost/boost/algorithm/cxx11/one_of.hpp
@@ -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
diff --git a/boost/boost/algorithm/cxx11/partition_copy.hpp b/boost/boost/algorithm/cxx11/partition_copy.hpp new file mode 100644 index 0000000..2d8c3e9 --- /dev/null +++ b/boost/boost/algorithm/cxx11/partition_copy.hpp
@@ -0,0 +1,73 @@ +/* + 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 { + +/// \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 ); +} + +/// \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
diff --git a/boost/boost/algorithm/cxx11/partition_point.hpp b/boost/boost/algorithm/cxx11/partition_point.hpp new file mode 100644 index 0000000..f1310c3 --- /dev/null +++ b/boost/boost/algorithm/cxx11/partition_point.hpp
@@ -0,0 +1,67 @@ +/* + 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 { + +/// \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; +} + +/// \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>::type partition_point ( Range &r, Predicate p ) +{ + return boost::algorithm::partition_point (boost::begin(r), boost::end(r), p); +} + + +}} + +#endif // BOOST_ALGORITHM_PARTITION_POINT_HPP
diff --git a/boost/boost/algorithm/cxx14/equal.hpp b/boost/boost/algorithm/cxx14/equal.hpp new file mode 100644 index 0000000..cfc62d5 --- /dev/null +++ b/boost/boost/algorithm/cxx14/equal.hpp
@@ -0,0 +1,97 @@ +/* + 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 equal.hpp +/// \brief Test ranges to if they are equal +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_EQUAL_HPP +#define BOOST_ALGORITHM_EQUAL_HPP + +#include <algorithm> // for std::equal +#include <functional> // for std::equal_to + +namespace boost { namespace algorithm { + +namespace detail { + + template <class T1, class T2> + struct eq : public std::binary_function<T1, T2, bool> { + bool operator () ( const T1& v1, const T2& v2 ) const { return v1 == v2 ;} + }; + + template <class RandomAccessIterator1, class RandomAccessIterator2, class BinaryPredicate> + bool equal ( RandomAccessIterator1 first1, RandomAccessIterator1 last1, + RandomAccessIterator2 first2, RandomAccessIterator2 last2, BinaryPredicate pred, + std::random_access_iterator_tag, std::random_access_iterator_tag ) + { + // Random-access iterators let is check the sizes in constant time + if ( std::distance ( first1, last1 ) != std::distance ( first2, last2 )) + return false; + // If we know that the sequences are the same size, the original version is fine + return std::equal ( first1, last1, first2, pred ); + } + + template <class InputIterator1, class InputIterator2, class BinaryPredicate> + bool equal ( InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred, + std::input_iterator_tag, std::input_iterator_tag ) + { + for (; first1 != last1 && first2 != last2; ++first1, ++first2 ) + if ( !pred(*first1, *first2 )) + return false; + + return first1 == last1 && first2 == last2; + } +} + +/// \fn equal ( InputIterator1 first1, InputIterator1 last1, +/// InputIterator2 first2, InputIterator2 last2, +/// BinaryPredicate pred ) +/// \return true if all elements in the two ranges are equal +/// +/// \param first1 The start of the first range. +/// \param last1 One past the end of the first range. +/// \param first2 The start of the second range. +/// \param last2 One past the end of the second range. +/// \param pred A predicate for comparing the elements of the ranges +template <class InputIterator1, class InputIterator2, class BinaryPredicate> +bool equal ( InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, BinaryPredicate pred ) +{ + return boost::algorithm::detail::equal ( + first1, last1, first2, last2, pred, + typename std::iterator_traits<InputIterator1>::iterator_category (), + typename std::iterator_traits<InputIterator2>::iterator_category ()); +} + +/// \fn equal ( InputIterator1 first1, InputIterator1 last1, +/// InputIterator2 first2, InputIterator2 last2 ) +/// \return true if all elements in the two ranges are equal +/// +/// \param first1 The start of the first range. +/// \param last1 One past the end of the first range. +/// \param first2 The start of the second range. +/// \param last2 One past the end of the second range. +template <class InputIterator1, class InputIterator2> +bool equal ( InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 ) +{ + return boost::algorithm::detail::equal ( + first1, last1, first2, last2, + boost::algorithm::detail::eq< + typename std::iterator_traits<InputIterator1>::value_type, + typename std::iterator_traits<InputIterator2>::value_type> (), + typename std::iterator_traits<InputIterator1>::iterator_category (), + typename std::iterator_traits<InputIterator2>::iterator_category ()); +} + +// There are already range-based versions of these. + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_EQUAL_HPP
diff --git a/boost/boost/algorithm/cxx14/is_permutation.hpp b/boost/boost/algorithm/cxx14/is_permutation.hpp new file mode 100644 index 0000000..9346881 --- /dev/null +++ b/boost/boost/algorithm/cxx14/is_permutation.hpp
@@ -0,0 +1,84 @@ +/* + Copyright (c) Marshall Clow 2014. + + Distributed under the 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 (four iterator versions) +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_IS_PERMUTATION14_HPP +#define BOOST_ALGORITHM_IS_PERMUTATION14_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/algorithm/cxx11/is_permutation.hpp> +#include <boost/algorithm/cxx14/mismatch.hpp> + +namespace boost { namespace algorithm { + +/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, +/// ForwardIterator2 first2, ForwardIterator2 last2 ) +/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 +/// +/// \param first1 The start of the input sequence +/// \param last2 One past the end of the input sequence +/// \param first2 The start of the second sequence +/// \param last1 One past the end of the second sequence +/// \note This function is part of the C++2014 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 first1, ForwardIterator1 last1, + ForwardIterator2 first2, ForwardIterator2 last2 ) +{ +// How should I deal with the idea that ForwardIterator1::value_type +// and ForwardIterator2::value_type could be different? Define my own comparison predicate? + std::pair<ForwardIterator1, ForwardIterator2> eq = boost::algorithm::mismatch + ( first1, last1, first2, last2 ); + if ( eq.first == last1 && eq.second == last2) + return true; + return boost::algorithm::detail::is_permutation_tag ( + eq.first, last1, eq.second, last2, + std::equal_to<typename std::iterator_traits<ForwardIterator1>::value_type> (), + typename std::iterator_traits<ForwardIterator1>::iterator_category (), + typename std::iterator_traits<ForwardIterator2>::iterator_category ()); +} + +/// \fn is_permutation ( ForwardIterator1 first, ForwardIterator1 last, +/// ForwardIterator2 first2, ForwardIterator2 last2, +/// BinaryPredicate p ) +/// \brief Tests to see if the sequence [first,last) is a permutation of the sequence starting at first2 +/// +/// \param first1 The start of the input sequence +/// \param last1 One past the end of the input sequence +/// \param first2 The start of the second sequence +/// \param last2 One past the end of the second sequence +/// \param pred The predicate to compare elements with +/// +/// \note This function is part of the C++2014 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, ForwardIterator2 last2, + BinaryPredicate pred ) +{ + std::pair<ForwardIterator1, ForwardIterator2> eq = boost::algorithm::mismatch + ( first1, last1, first2, last2, pred ); + if ( eq.first == last1 && eq.second == last2) + return true; + return boost::algorithm::detail::is_permutation_tag ( + first1, last1, first2, last2, pred, + typename std::iterator_traits<ForwardIterator1>::iterator_category (), + typename std::iterator_traits<ForwardIterator2>::iterator_category ()); +} + +}} + +#endif // BOOST_ALGORITHM_IS_PERMUTATION14_HPP
diff --git a/boost/boost/algorithm/cxx14/mismatch.hpp b/boost/boost/algorithm/cxx14/mismatch.hpp new file mode 100644 index 0000000..926ab19 --- /dev/null +++ b/boost/boost/algorithm/cxx14/mismatch.hpp
@@ -0,0 +1,65 @@ +/* + Copyright (c) Marshall Clow 2008-2012. + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE10.txt or copy at http://www.boost.org/LICENSE10.txt) +*/ + +/// \file mismatch.hpp +/// \brief Find the first mismatched element in a sequence +/// \author Marshall Clow + +#ifndef BOOST_ALGORITHM_MISMATCH_HPP +#define BOOST_ALGORITHM_MISMATCH_HPP + +#include <algorithm> // for std::mismatch +#include <utility> // for std::pair + +namespace boost { namespace algorithm { + +/// \fn mismatch ( InputIterator1 first1, InputIterator1 last1, +/// InputIterator2 first2, InputIterator2 last2, +/// BinaryPredicate pred ) +/// \return a pair of iterators pointing to the first elements in the sequence that do not match +/// +/// \param first1 The start of the first range. +/// \param last1 One past the end of the first range. +/// \param first2 The start of the second range. +/// \param last2 One past the end of the second range. +/// \param pred A predicate for comparing the elements of the ranges +template <class InputIterator1, class InputIterator2, class BinaryPredicate> +std::pair<InputIterator1, InputIterator2> mismatch ( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2, + BinaryPredicate pred ) +{ + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + if ( !pred ( *first1, *first2 )) + break; + return std::pair<InputIterator1, InputIterator2>(first1, first2); +} + +/// \fn mismatch ( InputIterator1 first1, InputIterator1 last1, +/// InputIterator2 first2, InputIterator2 last2 ) +/// \return a pair of iterators pointing to the first elements in the sequence that do not match +/// +/// \param first1 The start of the first range. +/// \param last1 One past the end of the first range. +/// \param first2 The start of the second range. +/// \param last2 One past the end of the second range. +template <class InputIterator1, class InputIterator2> +std::pair<InputIterator1, InputIterator2> mismatch ( + InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2 ) +{ + for (; first1 != last1 && first2 != last2; ++first1, ++first2) + if ( *first1 != *first2 ) + break; + return std::pair<InputIterator1, InputIterator2>(first1, first2); +} + +// There are already range-based versions of these. + +}} // namespace boost and algorithm + +#endif // BOOST_ALGORITHM_MISMATCH_HPP
diff --git a/boost/boost/algorithm/gather.hpp b/boost/boost/algorithm/gather.hpp new file mode 100644 index 0000000..944bc94 --- /dev/null +++ b/boost/boost/algorithm/gather.hpp
@@ -0,0 +1,123 @@ +/* + Copyright 2008 Adobe Systems Incorporated + + Distributed under the 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: + January 2008 mtc Version for Adobe Source Library + January 2013 mtc Version for Boost.Algorithm + +*/ + +/**************************************************************************************************/ + +/*! +\author Marshall Clow +\date January 2008 +*/ + +#ifndef BOOST_ALGORITHM_GATHER_HPP +#define BOOST_ALGORITHM_GATHER_HPP + +#include <algorithm> // for std::stable_partition +#include <functional> + +#include <boost/bind.hpp> // for boost::bind +#include <boost/range/begin.hpp> // for boost::begin(range) +#include <boost/range/end.hpp> // for boost::end(range) + + +/**************************************************************************************************/ +/*! + \defgroup gather gather + \ingroup mutating_algorithm + + \c gather() takes a collection of elements defined by a pair of iterators and moves + the ones satisfying a predicate to them to a position (called the pivot) within + the sequence. The algorithm is stable. The result is a pair of iterators that + contains the items that satisfy the predicate. + + Given an sequence containing: + <pre> + 0 1 2 3 4 5 6 7 8 9 + </pre> + + a call to gather ( arr, arr + 10, arr + 4, IsEven ()) will result in: + + <pre> + 1 3 0 2 4 6 8 5 7 9 + |---|-----| + first | second + pivot + </pre> + + + The problem is broken down into two basic steps, namely, moving the items before the pivot + and then moving the items from the pivot to the end. These "moves" are done with calls to + stable_partition. + + \par Storage Requirements: + + The algorithm uses stable_partition, which will attempt to allocate temporary memory, + but will work in-situ if there is none available. + + \par Time Complexity: + + If there is sufficient memory available, the run time is linear in <code>N</code>. + If there is not any memory available, then the run time is <code>O(N log N)</code>. +*/ + +/**************************************************************************************************/ + +namespace boost { namespace algorithm { + +/**************************************************************************************************/ + +/*! + \ingroup gather + \brief iterator-based gather implementation +*/ + +template < + typename BidirectionalIterator, // Iter models BidirectionalIterator + typename Pred> // Pred models UnaryPredicate +std::pair<BidirectionalIterator, BidirectionalIterator> gather + ( BidirectionalIterator first, BidirectionalIterator last, BidirectionalIterator pivot, Pred pred ) +{ +// The first call partitions everything up to (but not including) the pivot element, +// while the second call partitions the rest of the sequence. + return std::make_pair ( + std::stable_partition ( first, pivot, !boost::bind<bool> ( pred, _1 )), + std::stable_partition ( pivot, last, boost::bind<bool> ( pred, _1 ))); +} + +/**************************************************************************************************/ + +/*! + \ingroup gather + \brief range-based gather implementation +*/ + +template < + typename BidirectionalRange, // + typename Pred> // Pred models UnaryPredicate +std::pair< + typename boost::range_iterator<const BidirectionalRange>::type, + typename boost::range_iterator<const BidirectionalRange>::type> +gather ( + const BidirectionalRange &range, + typename boost::range_iterator<const BidirectionalRange>::type pivot, + Pred pred ) +{ + return boost::algorithm::gather ( boost::begin ( range ), boost::end ( range ), pivot, pred ); +} + +/**************************************************************************************************/ + +}} // namespace + +/**************************************************************************************************/ + +#endif +
diff --git a/boost/boost/algorithm/hex.hpp b/boost/boost/algorithm/hex.hpp new file mode 100644 index 0000000..145a414 --- /dev/null +++ b/boost/boost/algorithm/hex.hpp
@@ -0,0 +1,260 @@ +/* + 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. +*/ + +/// \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 ); + } + + template <typename T> + unsigned char hex_char_to_int ( T val ) { + char c = static_cast<char> ( val ); + unsigned retval = 0; + if ( c >= '0' && c <= '9' ) retval = c - '0'; + else if ( c >= 'A' && c <= 'F' ) retval = c - 'A' + 10; + else if ( c >= 'a' && c <= 'f' ) retval = c - 'a' + 10; + else BOOST_THROW_EXCEPTION (non_hex_input() << bad_char (c)); + return retval; + } + +// 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 (*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 ) { +// 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
diff --git a/boost/boost/algorithm/minmax.hpp b/boost/boost/algorithm/minmax.hpp new file mode 100644 index 0000000..053a7d6 --- /dev/null +++ b/boost/boost/algorithm/minmax.hpp
@@ -0,0 +1,47 @@ +// (C) Copyright Herve Bronnimann 2004. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/* + Revision history: + 1 July 2004 + Split the code into two headers to lessen dependence on + Boost.tuple. (Herve) + 26 June 2004 + Added the code for the boost minmax library. (Herve) +*/ + +#ifndef BOOST_ALGORITHM_MINMAX_HPP +#define BOOST_ALGORITHM_MINMAX_HPP + +/* PROPOSED STANDARD EXTENSIONS: + * + * minmax(a, b) + * Effect: (b<a) ? std::make_pair(b,a) : std::make_pair(a,b); + * + * minmax(a, b, comp) + * Effect: comp(b,a) ? std::make_pair(b,a) : std::make_pair(a,b); + * + */ + +#include <boost/tuple/tuple.hpp> // for using pairs with boost::cref +#include <boost/ref.hpp> + +namespace boost { + + template <typename T> + tuple< T const&, T const& > + minmax(T const& a, T const& b) { + return (b<a) ? make_tuple(cref(b),cref(a)) : make_tuple(cref(a),cref(b)); + } + + template <typename T, class BinaryPredicate> + tuple< T const&, T const& > + minmax(T const& a, T const& b, BinaryPredicate comp) { + return comp(b,a) ? make_tuple(cref(b),cref(a)) : make_tuple(cref(a),cref(b)); + } + +} // namespace boost + +#endif // BOOST_ALGORITHM_MINMAX_HPP
diff --git a/boost/boost/algorithm/minmax_element.hpp b/boost/boost/algorithm/minmax_element.hpp new file mode 100644 index 0000000..752f6cb --- /dev/null +++ b/boost/boost/algorithm/minmax_element.hpp
@@ -0,0 +1,553 @@ +// (C) Copyright Herve Bronnimann 2004. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/* + Revision history: + 1 July 2004 + Split the code into two headers to lessen dependence on + Boost.tuple. (Herve) + 26 June 2004 + Added the code for the boost minmax library. (Herve) +*/ + +#ifndef BOOST_ALGORITHM_MINMAX_ELEMENT_HPP +#define BOOST_ALGORITHM_MINMAX_ELEMENT_HPP + +/* PROPOSED STANDARD EXTENSIONS: + * + * minmax_element(first, last) + * Effect: std::make_pair( std::min_element(first, last), + * std::max_element(first, last) ); + * + * minmax_element(first, last, comp) + * Effect: std::make_pair( std::min_element(first, last, comp), + * std::max_element(first, last, comp) ); + */ + +#include <utility> // for std::pair and std::make_pair + +namespace boost { + + namespace detail { // for obtaining a uniform version of minmax_element + // that compiles with VC++ 6.0 -- avoid the iterator_traits by + // having comparison object over iterator, not over dereferenced value + + template <typename Iterator> + struct less_over_iter { + bool operator()(Iterator const& it1, + Iterator const& it2) const { return *it1 < *it2; } + }; + + template <typename Iterator, class BinaryPredicate> + struct binary_pred_over_iter { + explicit binary_pred_over_iter(BinaryPredicate const& p ) : m_p( p ) {} + bool operator()(Iterator const& it1, + Iterator const& it2) const { return m_p(*it1, *it2); } + private: + BinaryPredicate m_p; + }; + + // common base for the two minmax_element overloads + + template <typename ForwardIter, class Compare > + std::pair<ForwardIter,ForwardIter> + basic_minmax_element(ForwardIter first, ForwardIter last, Compare comp) + { + if (first == last) + return std::make_pair(last,last); + + ForwardIter min_result = first; + ForwardIter max_result = first; + + // if only one element + ForwardIter second = first; ++second; + if (second == last) + return std::make_pair(min_result, max_result); + + // treat first pair separately (only one comparison for first two elements) + ForwardIter potential_min_result = last; + if (comp(first, second)) + max_result = second; + else { + min_result = second; + potential_min_result = first; + } + + // then each element by pairs, with at most 3 comparisons per pair + first = ++second; if (first != last) ++second; + while (second != last) { + if (comp(first, second)) { + if (comp(first, min_result)) { + min_result = first; + potential_min_result = last; + } + if (comp(max_result, second)) + max_result = second; + } else { + if (comp(second, min_result)) { + min_result = second; + potential_min_result = first; + } + if (comp(max_result, first)) + max_result = first; + } + first = ++second; + if (first != last) ++second; + } + + // if odd number of elements, treat last element + if (first != last) { // odd number of elements + if (comp(first, min_result)) { + min_result = first; + potential_min_result = last; + } + else if (comp(max_result, first)) + max_result = first; + } + + // resolve min_result being incorrect with one extra comparison + // (in which case potential_min_result is necessarily the correct result) + if (potential_min_result != last + && !comp(min_result, potential_min_result)) + min_result = potential_min_result; + + return std::make_pair(min_result,max_result); + } + + } // namespace detail + + template <typename ForwardIter> + std::pair<ForwardIter,ForwardIter> + minmax_element(ForwardIter first, ForwardIter last) + { + return detail::basic_minmax_element(first, last, + detail::less_over_iter<ForwardIter>() ); + } + + template <typename ForwardIter, class BinaryPredicate> + std::pair<ForwardIter,ForwardIter> + minmax_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_minmax_element(first, last, + detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) ); + } + +} + +/* PROPOSED BOOST EXTENSIONS + * In the description below, [rfirst,rlast) denotes the reversed range + * of [first,last). Even though the iterator type of first and last may + * be only a Forward Iterator, it is possible to explain the semantics + * by assuming that it is a Bidirectional Iterator. In the sequel, + * reverse(ForwardIterator&) returns the reverse_iterator adaptor. + * This is not how the functions would be implemented! + * + * first_min_element(first, last) + * Effect: std::min_element(first, last); + * + * first_min_element(first, last, comp) + * Effect: std::min_element(first, last, comp); + * + * last_min_element(first, last) + * Effect: reverse( std::min_element(reverse(last), reverse(first)) ); + * + * last_min_element(first, last, comp) + * Effect: reverse( std::min_element(reverse(last), reverse(first), comp) ); + * + * first_max_element(first, last) + * Effect: std::max_element(first, last); + * + * first_max_element(first, last, comp) + * Effect: max_element(first, last); + * + * last_max_element(first, last) + * Effect: reverse( std::max_element(reverse(last), reverse(first)) ); + * + * last_max_element(first, last, comp) + * Effect: reverse( std::max_element(reverse(last), reverse(first), comp) ); + * + * first_min_first_max_element(first, last) + * Effect: std::make_pair( first_min_element(first, last), + * first_max_element(first, last) ); + * + * first_min_first_max_element(first, last, comp) + * Effect: std::make_pair( first_min_element(first, last, comp), + * first_max_element(first, last, comp) ); + * + * first_min_last_max_element(first, last) + * Effect: std::make_pair( first_min_element(first, last), + * last_max_element(first, last) ); + * + * first_min_last_max_element(first, last, comp) + * Effect: std::make_pair( first_min_element(first, last, comp), + * last_max_element(first, last, comp) ); + * + * last_min_first_max_element(first, last) + * Effect: std::make_pair( last_min_element(first, last), + * first_max_element(first, last) ); + * + * last_min_first_max_element(first, last, comp) + * Effect: std::make_pair( last_min_element(first, last, comp), + * first_max_element(first, last, comp) ); + * + * last_min_last_max_element(first, last) + * Effect: std::make_pair( last_min_element(first, last), + * last_max_element(first, last) ); + * + * last_min_last_max_element(first, last, comp) + * Effect: std::make_pair( last_min_element(first, last, comp), + * last_max_element(first, last, comp) ); + */ + +namespace boost { + + // Min_element and max_element variants + + namespace detail { // common base for the overloads + + template <typename ForwardIter, class BinaryPredicate> + ForwardIter + basic_first_min_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return last; + ForwardIter min_result = first; + while (++first != last) + if (comp(first, min_result)) + min_result = first; + return min_result; + } + + template <typename ForwardIter, class BinaryPredicate> + ForwardIter + basic_last_min_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return last; + ForwardIter min_result = first; + while (++first != last) + if (!comp(min_result, first)) + min_result = first; + return min_result; + } + + template <typename ForwardIter, class BinaryPredicate> + ForwardIter + basic_first_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return last; + ForwardIter max_result = first; + while (++first != last) + if (comp(max_result, first)) + max_result = first; + return max_result; + } + + template <typename ForwardIter, class BinaryPredicate> + ForwardIter + basic_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return last; + ForwardIter max_result = first; + while (++first != last) + if (!comp(first, max_result)) + max_result = first; + return max_result; + } + + } // namespace detail + + template <typename ForwardIter> + ForwardIter + first_min_element(ForwardIter first, ForwardIter last) + { + return detail::basic_first_min_element(first, last, + detail::less_over_iter<ForwardIter>() ); + } + + template <typename ForwardIter, class BinaryPredicate> + ForwardIter + first_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_first_min_element(first, last, + detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) ); + } + + template <typename ForwardIter> + ForwardIter + last_min_element(ForwardIter first, ForwardIter last) + { + return detail::basic_last_min_element(first, last, + detail::less_over_iter<ForwardIter>() ); + } + + template <typename ForwardIter, class BinaryPredicate> + ForwardIter + last_min_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_last_min_element(first, last, + detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) ); + } + + template <typename ForwardIter> + ForwardIter + first_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_first_max_element(first, last, + detail::less_over_iter<ForwardIter>() ); + } + + template <typename ForwardIter, class BinaryPredicate> + ForwardIter + first_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_first_max_element(first, last, + detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) ); + } + + template <typename ForwardIter> + ForwardIter + last_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_last_max_element(first, last, + detail::less_over_iter<ForwardIter>() ); + } + + template <typename ForwardIter, class BinaryPredicate> + ForwardIter + last_max_element(ForwardIter first, ForwardIter last, BinaryPredicate comp) + { + return detail::basic_last_max_element(first, last, + detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) ); + } + + + // Minmax_element variants -- comments removed + + namespace detail { + + template <typename ForwardIter, class BinaryPredicate> + std::pair<ForwardIter,ForwardIter> + basic_first_min_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) + return std::make_pair(last,last); + + ForwardIter min_result = first; + ForwardIter max_result = first; + + ForwardIter second = ++first; + if (second == last) + return std::make_pair(min_result, max_result); + + if (comp(second, min_result)) + min_result = second; + else + max_result = second; + + first = ++second; if (first != last) ++second; + while (second != last) { + if (!comp(second, first)) { + if (comp(first, min_result)) + min_result = first; + if (!comp(second, max_result)) + max_result = second; + } else { + if (comp(second, min_result)) + min_result = second; + if (!comp(first, max_result)) + max_result = first; + } + first = ++second; if (first != last) ++second; + } + + if (first != last) { + if (comp(first, min_result)) + min_result = first; + else if (!comp(first, max_result)) + max_result = first; + } + + return std::make_pair(min_result, max_result); + } + + template <typename ForwardIter, class BinaryPredicate> + std::pair<ForwardIter,ForwardIter> + basic_last_min_first_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return std::make_pair(last,last); + + ForwardIter min_result = first; + ForwardIter max_result = first; + + ForwardIter second = ++first; + if (second == last) + return std::make_pair(min_result, max_result); + + if (comp(max_result, second)) + max_result = second; + else + min_result = second; + + first = ++second; if (first != last) ++second; + while (second != last) { + if (comp(first, second)) { + if (!comp(min_result, first)) + min_result = first; + if (comp(max_result, second)) + max_result = second; + } else { + if (!comp(min_result, second)) + min_result = second; + if (comp(max_result, first)) + max_result = first; + } + first = ++second; if (first != last) ++second; + } + + if (first != last) { + if (!comp(min_result, first)) + min_result = first; + else if (comp(max_result, first)) + max_result = first; + } + + return std::make_pair(min_result, max_result); + } + + template <typename ForwardIter, class BinaryPredicate> + std::pair<ForwardIter,ForwardIter> + basic_last_min_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + if (first == last) return std::make_pair(last,last); + + ForwardIter min_result = first; + ForwardIter max_result = first; + + ForwardIter second = first; ++second; + if (second == last) + return std::make_pair(min_result,max_result); + + ForwardIter potential_max_result = last; + if (comp(first, second)) + max_result = second; + else { + min_result = second; + potential_max_result = second; + } + + first = ++second; if (first != last) ++second; + while (second != last) { + if (comp(first, second)) { + if (!comp(min_result, first)) + min_result = first; + if (!comp(second, max_result)) { + max_result = second; + potential_max_result = last; + } + } else { + if (!comp(min_result, second)) + min_result = second; + if (!comp(first, max_result)) { + max_result = first; + potential_max_result = second; + } + } + first = ++second; + if (first != last) ++second; + } + + if (first != last) { + if (!comp(min_result, first)) + min_result = first; + if (!comp(first, max_result)) { + max_result = first; + potential_max_result = last; + } + } + + if (potential_max_result != last + && !comp(potential_max_result, max_result)) + max_result = potential_max_result; + + return std::make_pair(min_result,max_result); + } + + } // namespace detail + + template <typename ForwardIter> + inline std::pair<ForwardIter,ForwardIter> + first_min_first_max_element(ForwardIter first, ForwardIter last) + { + return minmax_element(first, last); + } + + template <typename ForwardIter, class BinaryPredicate> + inline std::pair<ForwardIter,ForwardIter> + first_min_first_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + return minmax_element(first, last, comp); + } + + template <typename ForwardIter> + std::pair<ForwardIter,ForwardIter> + first_min_last_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_first_min_last_max_element(first, last, + detail::less_over_iter<ForwardIter>() ); + } + + template <typename ForwardIter, class BinaryPredicate> + inline std::pair<ForwardIter,ForwardIter> + first_min_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + return detail::basic_first_min_last_max_element(first, last, + detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) ); + } + + template <typename ForwardIter> + std::pair<ForwardIter,ForwardIter> + last_min_first_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_last_min_first_max_element(first, last, + detail::less_over_iter<ForwardIter>() ); + } + + template <typename ForwardIter, class BinaryPredicate> + inline std::pair<ForwardIter,ForwardIter> + last_min_first_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + return detail::basic_last_min_first_max_element(first, last, + detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) ); + } + + template <typename ForwardIter> + std::pair<ForwardIter,ForwardIter> + last_min_last_max_element(ForwardIter first, ForwardIter last) + { + return detail::basic_last_min_last_max_element(first, last, + detail::less_over_iter<ForwardIter>() ); + } + + template <typename ForwardIter, class BinaryPredicate> + inline std::pair<ForwardIter,ForwardIter> + last_min_last_max_element(ForwardIter first, ForwardIter last, + BinaryPredicate comp) + { + return detail::basic_last_min_last_max_element(first, last, + detail::binary_pred_over_iter<ForwardIter,BinaryPredicate>(comp) ); + } + +} // namespace boost + +#endif // BOOST_ALGORITHM_MINMAX_ELEMENT_HPP
diff --git a/boost/boost/algorithm/searching/boyer_moore.hpp b/boost/boost/algorithm/searching/boyer_moore.hpp new file mode 100644 index 0000000..c5fe9fa --- /dev/null +++ b/boost/boost/algorithm/searching/boyer_moore.hpp
@@ -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
diff --git a/boost/boost/algorithm/searching/boyer_moore_horspool.hpp b/boost/boost/algorithm/searching/boyer_moore_horspool.hpp new file mode 100644 index 0000000..758ded2 --- /dev/null +++ b/boost/boost/algorithm/searching/boyer_moore_horspool.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
diff --git a/boost/boost/algorithm/searching/detail/bm_traits.hpp b/boost/boost/algorithm/searching/detail/bm_traits.hpp new file mode 100644 index 0000000..b39e539 --- /dev/null +++ b/boost/boost/algorithm/searching/detail/bm_traits.hpp
@@ -0,0 +1,113 @@ +/* + 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> +#ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP +#include <boost/unordered_map.hpp> +#else +#include <unordered_map> +#endif + +#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: +#ifdef BOOST_NO_CXX11_HDR_UNORDERED_MAP + typedef boost::unordered_map<key_type, value_type> skip_map; +#else + typedef std::unordered_map<key_type, value_type> skip_map; +#endif + 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
diff --git a/boost/boost/algorithm/searching/detail/debugging.hpp b/boost/boost/algorithm/searching/detail/debugging.hpp new file mode 100644 index 0000000..3996e0f --- /dev/null +++ b/boost/boost/algorithm/searching/detail/debugging.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
diff --git a/boost/boost/algorithm/searching/knuth_morris_pratt.hpp b/boost/boost/algorithm/searching/knuth_morris_pratt.hpp new file mode 100644 index 0000000..aaeeb51 --- /dev/null +++ b/boost/boost/algorithm/searching/knuth_morris_pratt.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
diff --git a/boost/boost/algorithm/string.hpp b/boost/boost/algorithm/string.hpp new file mode 100644 index 0000000..0771517 --- /dev/null +++ b/boost/boost/algorithm/string.hpp
@@ -0,0 +1,31 @@ +// Boost string_algo library string_algo.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2004. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_ALGO_HPP +#define BOOST_STRING_ALGO_HPP + +/*! \file + Cumulative include for string_algo library +*/ + +#include <boost/algorithm/string/std_containers_traits.hpp> +#include <boost/algorithm/string/trim.hpp> +#include <boost/algorithm/string/case_conv.hpp> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/algorithm/string/find.hpp> +#include <boost/algorithm/string/split.hpp> +#include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/replace.hpp> +#include <boost/algorithm/string/erase.hpp> +#include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/find_iterator.hpp> + + +#endif // BOOST_STRING_ALGO_HPP
diff --git a/boost/boost/algorithm/string/case_conv.hpp b/boost/boost/algorithm/string/case_conv.hpp new file mode 100644 index 0000000..683340b --- /dev/null +++ b/boost/boost/algorithm/string/case_conv.hpp
@@ -0,0 +1,176 @@ +// Boost string_algo library case_conv.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CASE_CONV_HPP +#define BOOST_STRING_CASE_CONV_HPP + +#include <boost/algorithm/string/config.hpp> +#include <algorithm> +#include <locale> +#include <boost/iterator/transform_iterator.hpp> + +#include <boost/range/as_literal.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/value_type.hpp> + +#include <boost/algorithm/string/detail/case_conv.hpp> + +/*! \file + Defines sequence case-conversion algorithms. + Algorithms convert each element in the input sequence to the + desired case using provided locales. +*/ + +namespace boost { + namespace algorithm { + +// to_lower -----------------------------------------------// + + //! Convert to lower case + /*! + Each element of the input sequence is converted to lower + case. The result is a copy of the input converted to lower case. + It is returned as a sequence or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param Loc A locale used for conversion + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + + */ + template<typename OutputIteratorT, typename RangeT> + inline OutputIteratorT + to_lower_copy( + OutputIteratorT Output, + const RangeT& Input, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::detail::transform_range_copy( + Output, + ::boost::as_literal(Input), + ::boost::algorithm::detail::to_lowerF< + typename range_value<RangeT>::type >(Loc)); + } + + //! Convert to lower case + /*! + \overload + */ + template<typename SequenceT> + inline SequenceT to_lower_copy( + const SequenceT& Input, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::detail::transform_range_copy<SequenceT>( + Input, + ::boost::algorithm::detail::to_lowerF< + typename range_value<SequenceT>::type >(Loc)); + } + + //! Convert to lower case + /*! + Each element of the input sequence is converted to lower + case. The input sequence is modified in-place. + + \param Input A range + \param Loc a locale used for conversion + */ + template<typename WritableRangeT> + inline void to_lower( + WritableRangeT& Input, + const std::locale& Loc=std::locale()) + { + ::boost::algorithm::detail::transform_range( + ::boost::as_literal(Input), + ::boost::algorithm::detail::to_lowerF< + typename range_value<WritableRangeT>::type >(Loc)); + } + +// to_upper -----------------------------------------------// + + //! Convert to upper case + /*! + Each element of the input sequence is converted to upper + case. The result is a copy of the input converted to upper case. + It is returned as a sequence or copied to the output iterator + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param Loc A locale used for conversion + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template<typename OutputIteratorT, typename RangeT> + inline OutputIteratorT + to_upper_copy( + OutputIteratorT Output, + const RangeT& Input, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::detail::transform_range_copy( + Output, + ::boost::as_literal(Input), + ::boost::algorithm::detail::to_upperF< + typename range_value<RangeT>::type >(Loc)); + } + + //! Convert to upper case + /*! + \overload + */ + template<typename SequenceT> + inline SequenceT to_upper_copy( + const SequenceT& Input, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::detail::transform_range_copy<SequenceT>( + Input, + ::boost::algorithm::detail::to_upperF< + typename range_value<SequenceT>::type >(Loc)); + } + + //! Convert to upper case + /*! + Each element of the input sequence is converted to upper + case. The input sequence is modified in-place. + + \param Input An input range + \param Loc a locale used for conversion + */ + template<typename WritableRangeT> + inline void to_upper( + WritableRangeT& Input, + const std::locale& Loc=std::locale()) + { + ::boost::algorithm::detail::transform_range( + ::boost::as_literal(Input), + ::boost::algorithm::detail::to_upperF< + typename range_value<WritableRangeT>::type >(Loc)); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::to_lower; + using algorithm::to_lower_copy; + using algorithm::to_upper; + using algorithm::to_upper_copy; + +} // namespace boost + +#endif // BOOST_STRING_CASE_CONV_HPP
diff --git a/boost/boost/algorithm/string/classification.hpp b/boost/boost/algorithm/string/classification.hpp new file mode 100644 index 0000000..ca43602 --- /dev/null +++ b/boost/boost/algorithm/string/classification.hpp
@@ -0,0 +1,312 @@ +// Boost string_algo library classification.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CLASSIFICATION_HPP +#define BOOST_STRING_CLASSIFICATION_HPP + +#include <algorithm> +#include <locale> +#include <boost/range/value_type.hpp> +#include <boost/range/as_literal.hpp> +#include <boost/algorithm/string/detail/classification.hpp> +#include <boost/algorithm/string/predicate_facade.hpp> + + +/*! \file + Classification predicates are included in the library to give + some more convenience when using algorithms like \c trim() and \c all(). + They wrap functionality of STL classification functions ( e.g. \c std::isspace() ) + into generic functors. +*/ + +namespace boost { + namespace algorithm { + +// classification functor generator -------------------------------------// + + //! is_classified predicate + /*! + Construct the \c is_classified predicate. This predicate holds if the input is + of specified \c std::ctype category. + + \param Type A \c std::ctype category + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_classified(std::ctype_base::mask Type, const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(Type, Loc); + } + + //! is_space predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::space category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_space(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::space, Loc); + } + + //! is_alnum predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::alnum category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_alnum(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::alnum, Loc); + } + + //! is_alpha predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::alpha category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_alpha(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::alpha, Loc); + } + + //! is_cntrl predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::cntrl category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_cntrl(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::cntrl, Loc); + } + + //! is_digit predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::digit category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_digit(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::digit, Loc); + } + + //! is_graph predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::graph category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_graph(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::graph, Loc); + } + + //! is_lower predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::lower category. + + \param Loc A locale used for classification + \return An instance of \c is_classified predicate + */ + inline detail::is_classifiedF + is_lower(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::lower, Loc); + } + + //! is_print predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::print category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_print(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::print, Loc); + } + + //! is_punct predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::punct category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_punct(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::punct, Loc); + } + + //! is_upper predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::upper category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_upper(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::upper, Loc); + } + + //! is_xdigit predicate + /*! + Construct the \c is_classified predicate for the \c ctype_base::xdigit category. + + \param Loc A locale used for classification + \return An instance of the \c is_classified predicate + */ + inline detail::is_classifiedF + is_xdigit(const std::locale& Loc=std::locale()) + { + return detail::is_classifiedF(std::ctype_base::xdigit, Loc); + } + + //! is_any_of predicate + /*! + Construct the \c is_any_of predicate. The predicate holds if the input + is included in the specified set of characters. + + \param Set A set of characters to be recognized + \return An instance of the \c is_any_of predicate + */ + template<typename RangeT> + inline detail::is_any_ofF< + BOOST_STRING_TYPENAME range_value<RangeT>::type> + is_any_of( const RangeT& Set ) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_set(boost::as_literal(Set)); + return detail::is_any_ofF<BOOST_STRING_TYPENAME range_value<RangeT>::type>(lit_set); + } + + //! is_from_range predicate + /*! + Construct the \c is_from_range predicate. The predicate holds if the input + is included in the specified range. (i.e. From <= Ch <= To ) + + \param From The start of the range + \param To The end of the range + \return An instance of the \c is_from_range predicate + */ + template<typename CharT> + inline detail::is_from_rangeF<CharT> is_from_range(CharT From, CharT To) + { + return detail::is_from_rangeF<CharT>(From,To); + } + + // predicate combinators ---------------------------------------------------// + + //! predicate 'and' composition predicate + /*! + Construct the \c class_and predicate. This predicate can be used + to logically combine two classification predicates. \c class_and holds, + if both predicates return true. + + \param Pred1 The first predicate + \param Pred2 The second predicate + \return An instance of the \c class_and predicate + */ + template<typename Pred1T, typename Pred2T> + inline detail::pred_andF<Pred1T, Pred2T> + operator&&( + const predicate_facade<Pred1T>& Pred1, + const predicate_facade<Pred2T>& Pred2 ) + { + // Doing the static_cast with the pointer instead of the reference + // is a workaround for some compilers which have problems with + // static_cast's of template references, i.e. CW8. /grafik/ + return detail::pred_andF<Pred1T,Pred2T>( + *static_cast<const Pred1T*>(&Pred1), + *static_cast<const Pred2T*>(&Pred2) ); + } + + //! predicate 'or' composition predicate + /*! + Construct the \c class_or predicate. This predicate can be used + to logically combine two classification predicates. \c class_or holds, + if one of the predicates return true. + + \param Pred1 The first predicate + \param Pred2 The second predicate + \return An instance of the \c class_or predicate + */ + template<typename Pred1T, typename Pred2T> + inline detail::pred_orF<Pred1T, Pred2T> + operator||( + const predicate_facade<Pred1T>& Pred1, + const predicate_facade<Pred2T>& Pred2 ) + { + // Doing the static_cast with the pointer instead of the reference + // is a workaround for some compilers which have problems with + // static_cast's of template references, i.e. CW8. /grafik/ + return detail::pred_orF<Pred1T,Pred2T>( + *static_cast<const Pred1T*>(&Pred1), + *static_cast<const Pred2T*>(&Pred2)); + } + + //! predicate negation operator + /*! + Construct the \c class_not predicate. This predicate represents a negation. + \c class_or holds if of the predicates return false. + + \param Pred The predicate to be negated + \return An instance of the \c class_not predicate + */ + template<typename PredT> + inline detail::pred_notF<PredT> + operator!( const predicate_facade<PredT>& Pred ) + { + // Doing the static_cast with the pointer instead of the reference + // is a workaround for some compilers which have problems with + // static_cast's of template references, i.e. CW8. /grafik/ + return detail::pred_notF<PredT>(*static_cast<const PredT*>(&Pred)); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::is_classified; + using algorithm::is_space; + using algorithm::is_alnum; + using algorithm::is_alpha; + using algorithm::is_cntrl; + using algorithm::is_digit; + using algorithm::is_graph; + using algorithm::is_lower; + using algorithm::is_upper; + using algorithm::is_print; + using algorithm::is_punct; + using algorithm::is_xdigit; + using algorithm::is_any_of; + using algorithm::is_from_range; + +} // namespace boost + +#endif // BOOST_STRING_PREDICATE_HPP
diff --git a/boost/boost/algorithm/string/compare.hpp b/boost/boost/algorithm/string/compare.hpp new file mode 100644 index 0000000..734303a --- /dev/null +++ b/boost/boost/algorithm/string/compare.hpp
@@ -0,0 +1,199 @@ +// Boost string_algo library compare.hpp header file -------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_COMPARE_HPP +#define BOOST_STRING_COMPARE_HPP + +#include <boost/algorithm/string/config.hpp> +#include <locale> + +/*! \file + Defines element comparison predicates. Many algorithms in this library can + take an additional argument with a predicate used to compare elements. + This makes it possible, for instance, to have case insensitive versions + of the algorithms. +*/ + +namespace boost { + namespace algorithm { + + // is_equal functor -----------------------------------------------// + + //! is_equal functor + /*! + Standard STL equal_to only handle comparison between arguments + of the same type. This is a less restrictive version which wraps operator ==. + */ + struct is_equal + { + //! Function operator + /*! + Compare two operands for equality + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + return Arg1==Arg2; + } + }; + + //! case insensitive version of is_equal + /*! + Case insensitive comparison predicate. Comparison is done using + specified locales. + */ + struct is_iequal + { + //! Constructor + /*! + \param Loc locales used for comparison + */ + is_iequal( const std::locale& Loc=std::locale() ) : + m_Loc( Loc ) {} + + //! Function operator + /*! + Compare two operands. Case is ignored. + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::toupper(Arg1)==std::toupper(Arg2); + #else + return std::toupper<T1>(Arg1,m_Loc)==std::toupper<T2>(Arg2,m_Loc); + #endif + } + + private: + std::locale m_Loc; + }; + + // is_less functor -----------------------------------------------// + + //! is_less functor + /*! + Convenient version of standard std::less. Operation is templated, therefore it is + not required to specify the exact types upon the construction + */ + struct is_less + { + //! Functor operation + /*! + Compare two operands using > operator + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + return Arg1<Arg2; + } + }; + + + //! case insensitive version of is_less + /*! + Case insensitive comparison predicate. Comparison is done using + specified locales. + */ + struct is_iless + { + //! Constructor + /*! + \param Loc locales used for comparison + */ + is_iless( const std::locale& Loc=std::locale() ) : + m_Loc( Loc ) {} + + //! Function operator + /*! + Compare two operands. Case is ignored. + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::toupper(Arg1)<std::toupper(Arg2); + #else + return std::toupper<T1>(Arg1,m_Loc)<std::toupper<T2>(Arg2,m_Loc); + #endif + } + + private: + std::locale m_Loc; + }; + + // is_not_greater functor -----------------------------------------------// + + //! is_not_greater functor + /*! + Convenient version of standard std::not_greater_to. Operation is templated, therefore it is + not required to specify the exact types upon the construction + */ + struct is_not_greater + { + //! Functor operation + /*! + Compare two operands using > operator + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + return Arg1<=Arg2; + } + }; + + + //! case insensitive version of is_not_greater + /*! + Case insensitive comparison predicate. Comparison is done using + specified locales. + */ + struct is_not_igreater + { + //! Constructor + /*! + \param Loc locales used for comparison + */ + is_not_igreater( const std::locale& Loc=std::locale() ) : + m_Loc( Loc ) {} + + //! Function operator + /*! + Compare two operands. Case is ignored. + */ + template< typename T1, typename T2 > + bool operator()( const T1& Arg1, const T2& Arg2 ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::toupper(Arg1)<=std::toupper(Arg2); + #else + return std::toupper<T1>(Arg1,m_Loc)<=std::toupper<T2>(Arg2,m_Loc); + #endif + } + + private: + std::locale m_Loc; + }; + + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::is_equal; + using algorithm::is_iequal; + using algorithm::is_less; + using algorithm::is_iless; + using algorithm::is_not_greater; + using algorithm::is_not_igreater; + +} // namespace boost + + +#endif // BOOST_STRING_COMPARE_HPP
diff --git a/boost/boost/algorithm/string/concept.hpp b/boost/boost/algorithm/string/concept.hpp new file mode 100644 index 0000000..17e8349 --- /dev/null +++ b/boost/boost/algorithm/string/concept.hpp
@@ -0,0 +1,83 @@ +// Boost string_algo library concept.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CONCEPT_HPP +#define BOOST_STRING_CONCEPT_HPP + +#include <boost/concept_check.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> + +/*! \file + Defines concepts used in string_algo library +*/ + +namespace boost { + namespace algorithm { + + //! Finder concept + /*! + Defines the Finder concept. Finder is a functor which selects + an arbitrary part of a string. Search is performed on + the range specified by starting and ending iterators. + + Result of the find operation must be convertible to iterator_range. + */ + template<typename FinderT, typename IteratorT> + struct FinderConcept + { + private: + typedef iterator_range<IteratorT> range; + public: + void constraints() + { + // Operation + r=(*pF)(i,i); + } + private: + range r; + IteratorT i; + FinderT* pF; + }; // Finder_concept + + + //! Formatter concept + /*! + Defines the Formatter concept. Formatter is a functor, which + takes a result from a finder operation and transforms it + in a specific way. + + Result must be a container supported by container_traits, + or a reference to it. + */ + template<typename FormatterT, typename FinderT, typename IteratorT> + struct FormatterConcept + { + public: + void constraints() + { + // Operation + ::boost::begin((*pFo)( (*pF)(i,i) )); + ::boost::end((*pFo)( (*pF)(i,i) )); + } + private: + IteratorT i; + FinderT* pF; + FormatterT *pFo; + }; // FormatterConcept; + + } // namespace algorithm +} // namespace boost + + + + +#endif // BOOST_STRING_CONCEPT_HPP
diff --git a/boost/boost/algorithm/string/config.hpp b/boost/boost/algorithm/string/config.hpp new file mode 100644 index 0000000..559750a --- /dev/null +++ b/boost/boost/algorithm/string/config.hpp
@@ -0,0 +1,28 @@ +// Boost string_algo library config.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CONFIG_HPP +#define BOOST_STRING_CONFIG_HPP + +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> + +#ifdef BOOST_STRING_DEDUCED_TYPENAME +# error "macro already defined!" +#endif + +#define BOOST_STRING_TYPENAME BOOST_DEDUCED_TYPENAME + +// Metrowerks workaround +#if BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x +#pragma parse_func_templ off +#endif + +#endif // BOOST_STRING_CONFIG_HPP
diff --git a/boost/boost/algorithm/string/constants.hpp b/boost/boost/algorithm/string/constants.hpp new file mode 100644 index 0000000..6ed70ef --- /dev/null +++ b/boost/boost/algorithm/string/constants.hpp
@@ -0,0 +1,36 @@ +// Boost string_algo library constants.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CONSTANTS_HPP +#define BOOST_STRING_CONSTANTS_HPP + +namespace boost { + namespace algorithm { + + //! Token compression mode + /*! + Specifies token compression mode for the token_finder. + */ + enum token_compress_mode_type + { + token_compress_on, //!< Compress adjacent tokens + token_compress_off //!< Do not compress adjacent tokens + }; + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::token_compress_on; + using algorithm::token_compress_off; + +} // namespace boost + +#endif // BOOST_STRING_CONSTANTS_HPP +
diff --git a/boost/boost/algorithm/string/detail/case_conv.hpp b/boost/boost/algorithm/string/detail/case_conv.hpp new file mode 100644 index 0000000..42621c7 --- /dev/null +++ b/boost/boost/algorithm/string/detail/case_conv.hpp
@@ -0,0 +1,123 @@ +// Boost string_algo library string_funct.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CASE_CONV_DETAIL_HPP +#define BOOST_STRING_CASE_CONV_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <locale> +#include <functional> + +#include <boost/type_traits/make_unsigned.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// case conversion functors -----------------------------------------------// + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(push) +#pragma warning(disable:4512) //assignment operator could not be generated +#endif + + // a tolower functor + template<typename CharT> + struct to_lowerF : public std::unary_function<CharT, CharT> + { + // Constructor + to_lowerF( const std::locale& Loc ) : m_Loc( &Loc ) {} + + // Operation + CharT operator ()( CharT Ch ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::tolower( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch )); + #else + return std::tolower<CharT>( Ch, *m_Loc ); + #endif + } + private: + const std::locale* m_Loc; + }; + + // a toupper functor + template<typename CharT> + struct to_upperF : public std::unary_function<CharT, CharT> + { + // Constructor + to_upperF( const std::locale& Loc ) : m_Loc( &Loc ) {} + + // Operation + CharT operator ()( CharT Ch ) const + { + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x564) && !defined(_USE_OLD_RW_STL) + return std::toupper( static_cast<typename boost::make_unsigned <CharT>::type> ( Ch )); + #else + return std::toupper<CharT>( Ch, *m_Loc ); + #endif + } + private: + const std::locale* m_Loc; + }; + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(pop) +#endif + +// algorithm implementation ------------------------------------------------------------------------- + + // Transform a range + template<typename OutputIteratorT, typename RangeT, typename FunctorT> + OutputIteratorT transform_range_copy( + OutputIteratorT Output, + const RangeT& Input, + FunctorT Functor) + { + return std::transform( + ::boost::begin(Input), + ::boost::end(Input), + Output, + Functor); + } + + // Transform a range (in-place) + template<typename RangeT, typename FunctorT> + void transform_range( + const RangeT& Input, + FunctorT Functor) + { + std::transform( + ::boost::begin(Input), + ::boost::end(Input), + ::boost::begin(Input), + Functor); + } + + template<typename SequenceT, typename RangeT, typename FunctorT> + inline SequenceT transform_range_copy( + const RangeT& Input, + FunctorT Functor) + { + return SequenceT( + ::boost::make_transform_iterator( + ::boost::begin(Input), + Functor), + ::boost::make_transform_iterator( + ::boost::end(Input), + Functor)); + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_CASE_CONV_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/classification.hpp b/boost/boost/algorithm/string/detail/classification.hpp new file mode 100644 index 0000000..704d9d2 --- /dev/null +++ b/boost/boost/algorithm/string/detail/classification.hpp
@@ -0,0 +1,353 @@ +// Boost string_algo library classification.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_CLASSIFICATION_DETAIL_HPP +#define BOOST_STRING_CLASSIFICATION_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <algorithm> +#include <functional> +#include <locale> + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> + +#include <boost/algorithm/string/predicate_facade.hpp> +#include <boost/type_traits/remove_const.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// classification functors -----------------------------------------------// + + // is_classified functor + struct is_classifiedF : + public predicate_facade<is_classifiedF> + { + // Boost.ResultOf support + typedef bool result_type; + + // Constructor from a locale + is_classifiedF(std::ctype_base::mask Type, std::locale const & Loc = std::locale()) : + m_Type(Type), m_Locale(Loc) {} + // Operation + template<typename CharT> + bool operator()( CharT Ch ) const + { + return std::use_facet< std::ctype<CharT> >(m_Locale).is( m_Type, Ch ); + } + + #if defined(__BORLANDC__) && (__BORLANDC__ >= 0x560) && (__BORLANDC__ <= 0x582) && !defined(_USE_OLD_RW_STL) + template<> + bool operator()( char const Ch ) const + { + return std::use_facet< std::ctype<char> >(m_Locale).is( m_Type, Ch ); + } + #endif + + private: + std::ctype_base::mask m_Type; + std::locale m_Locale; + }; + + + // is_any_of functor + /* + returns true if the value is from the specified set + */ + template<typename CharT> + struct is_any_ofF : + public predicate_facade<is_any_ofF<CharT> > + { + private: + // set cannot operate on const value-type + typedef typename ::boost::remove_const<CharT>::type set_value_type; + + public: + // Boost.ResultOf support + typedef bool result_type; + + // Constructor + template<typename RangeT> + is_any_ofF( const RangeT& Range ) : m_Size(0) + { + // Prepare storage + m_Storage.m_dynSet=0; + + std::size_t Size=::boost::distance(Range); + m_Size=Size; + set_value_type* Storage=0; + + if(use_fixed_storage(m_Size)) + { + // Use fixed storage + Storage=&m_Storage.m_fixSet[0]; + } + else + { + // Use dynamic storage + m_Storage.m_dynSet=new set_value_type[m_Size]; + Storage=m_Storage.m_dynSet; + } + + // Use fixed storage + ::std::copy(::boost::begin(Range), ::boost::end(Range), Storage); + ::std::sort(Storage, Storage+m_Size); + } + + // Copy constructor + is_any_ofF(const is_any_ofF& Other) : m_Size(Other.m_Size) + { + // Prepare storage + m_Storage.m_dynSet=0; + const set_value_type* SrcStorage=0; + set_value_type* DestStorage=0; + + if(use_fixed_storage(m_Size)) + { + // Use fixed storage + DestStorage=&m_Storage.m_fixSet[0]; + SrcStorage=&Other.m_Storage.m_fixSet[0]; + } + else + { + // Use dynamic storage + m_Storage.m_dynSet=new set_value_type[m_Size]; + DestStorage=m_Storage.m_dynSet; + SrcStorage=Other.m_Storage.m_dynSet; + } + + // Use fixed storage + ::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size); + } + + // Destructor + ~is_any_ofF() + { + if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0) + { + delete [] m_Storage.m_dynSet; + } + } + + // Assignment + is_any_ofF& operator=(const is_any_ofF& Other) + { + // Handle self assignment + if(this==&Other) return *this; + + // Prepare storage + const set_value_type* SrcStorage; + set_value_type* DestStorage; + + if(use_fixed_storage(Other.m_Size)) + { + // Use fixed storage + DestStorage=&m_Storage.m_fixSet[0]; + SrcStorage=&Other.m_Storage.m_fixSet[0]; + + // Delete old storage if was present + if(!use_fixed_storage(m_Size) && m_Storage.m_dynSet!=0) + { + delete [] m_Storage.m_dynSet; + } + + // Set new size + m_Size=Other.m_Size; + } + else + { + // Other uses dynamic storage + SrcStorage=Other.m_Storage.m_dynSet; + + // Check what kind of storage are we using right now + if(use_fixed_storage(m_Size)) + { + // Using fixed storage, allocate new + set_value_type* pTemp=new set_value_type[Other.m_Size]; + DestStorage=pTemp; + m_Storage.m_dynSet=pTemp; + m_Size=Other.m_Size; + } + else + { + // Using dynamic storage, check if can reuse + if(m_Storage.m_dynSet!=0 && m_Size>=Other.m_Size && m_Size<Other.m_Size*2) + { + // Reuse the current storage + DestStorage=m_Storage.m_dynSet; + m_Size=Other.m_Size; + } + else + { + // Allocate the new one + set_value_type* pTemp=new set_value_type[Other.m_Size]; + DestStorage=pTemp; + + // Delete old storage if necessary + if(m_Storage.m_dynSet!=0) + { + delete [] m_Storage.m_dynSet; + } + // Store the new storage + m_Storage.m_dynSet=pTemp; + // Set new size + m_Size=Other.m_Size; + } + } + } + + // Copy the data + ::std::memcpy(DestStorage, SrcStorage, sizeof(set_value_type)*m_Size); + + return *this; + } + + // Operation + template<typename Char2T> + bool operator()( Char2T Ch ) const + { + const set_value_type* Storage= + (use_fixed_storage(m_Size)) + ? &m_Storage.m_fixSet[0] + : m_Storage.m_dynSet; + + return ::std::binary_search(Storage, Storage+m_Size, Ch); + } + private: + // check if the size is eligible for fixed storage + static bool use_fixed_storage(std::size_t size) + { + return size<=sizeof(set_value_type*)*2; + } + + + private: + // storage + // The actual used storage is selected on the type + union + { + set_value_type* m_dynSet; + set_value_type m_fixSet[sizeof(set_value_type*)*2]; + } + m_Storage; + + // storage size + ::std::size_t m_Size; + }; + + // is_from_range functor + /* + returns true if the value is from the specified range. + (i.e. x>=From && x>=To) + */ + template<typename CharT> + struct is_from_rangeF : + public predicate_facade< is_from_rangeF<CharT> > + { + // Boost.ResultOf support + typedef bool result_type; + + // Constructor + is_from_rangeF( CharT From, CharT To ) : m_From(From), m_To(To) {} + + // Operation + template<typename Char2T> + bool operator()( Char2T Ch ) const + { + return ( m_From <= Ch ) && ( Ch <= m_To ); + } + + private: + CharT m_From; + CharT m_To; + }; + + // class_and composition predicate + template<typename Pred1T, typename Pred2T> + struct pred_andF : + public predicate_facade< pred_andF<Pred1T,Pred2T> > + { + public: + + // Boost.ResultOf support + typedef bool result_type; + + // Constructor + pred_andF( Pred1T Pred1, Pred2T Pred2 ) : + m_Pred1(Pred1), m_Pred2(Pred2) {} + + // Operation + template<typename CharT> + bool operator()( CharT Ch ) const + { + return m_Pred1(Ch) && m_Pred2(Ch); + } + + private: + Pred1T m_Pred1; + Pred2T m_Pred2; + }; + + // class_or composition predicate + template<typename Pred1T, typename Pred2T> + struct pred_orF : + public predicate_facade< pred_orF<Pred1T,Pred2T> > + { + public: + // Boost.ResultOf support + typedef bool result_type; + + // Constructor + pred_orF( Pred1T Pred1, Pred2T Pred2 ) : + m_Pred1(Pred1), m_Pred2(Pred2) {} + + // Operation + template<typename CharT> + bool operator()( CharT Ch ) const + { + return m_Pred1(Ch) || m_Pred2(Ch); + } + + private: + Pred1T m_Pred1; + Pred2T m_Pred2; + }; + + // class_not composition predicate + template< typename PredT > + struct pred_notF : + public predicate_facade< pred_notF<PredT> > + { + public: + // Boost.ResultOf support + typedef bool result_type; + + // Constructor + pred_notF( PredT Pred ) : m_Pred(Pred) {} + + // Operation + template<typename CharT> + bool operator()( CharT Ch ) const + { + return !m_Pred(Ch); + } + + private: + PredT m_Pred; + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/find_format.hpp b/boost/boost/algorithm/string/detail/find_format.hpp new file mode 100644 index 0000000..b398750 --- /dev/null +++ b/boost/boost/algorithm/string/detail/find_format.hpp
@@ -0,0 +1,204 @@ +// Boost string_algo library find_format.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_FORMAT_DETAIL_HPP +#define BOOST_STRING_FIND_FORMAT_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/const_iterator.hpp> +#include <boost/range/iterator.hpp> +#include <boost/algorithm/string/detail/find_format_store.hpp> +#include <boost/algorithm/string/detail/replace_storage.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// find_format_copy (iterator variant) implementation -------------------------------// + + template< + typename OutputIteratorT, + typename InputT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline OutputIteratorT find_format_copy_impl2( + OutputIteratorT Output, + const InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult ) + { + typedef find_format_store< + BOOST_STRING_TYPENAME + range_const_iterator<InputT>::type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + if ( !M ) + { + // Match not found - return original sequence + Output = std::copy( ::boost::begin(Input), ::boost::end(Input), Output ); + return Output; + } + + // Copy the beginning of the sequence + Output = std::copy( ::boost::begin(Input), ::boost::begin(M), Output ); + // Format find 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 ); + + return Output; + } + + template< + typename OutputIteratorT, + typename InputT, + typename FormatterT, + typename FindResultT > + inline OutputIteratorT find_format_copy_impl( + OutputIteratorT Output, + const InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult ) + { + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + return ::boost::algorithm::detail::find_format_copy_impl2( + Output, + Input, + Formatter, + FindResult, + Formatter(FindResult) ); + } else { + return std::copy( ::boost::begin(Input), ::boost::end(Input), Output ); + } + } + + +// find_format_copy implementation --------------------------------------------------// + + template< + typename InputT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline InputT find_format_copy_impl2( + const InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult) + { + typedef find_format_store< + BOOST_STRING_TYPENAME + range_const_iterator<InputT>::type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + if ( !M ) + { + // Match not found - return original sequence + return InputT( Input ); + } + + InputT Output; + // Copy the beginning of the sequence + 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 + boost::algorithm::detail::insert( Output, ::boost::end(Output), M.end(), ::boost::end(Input) ); + + return Output; + } + + template< + typename InputT, + typename FormatterT, + typename FindResultT > + inline InputT find_format_copy_impl( + const InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult) + { + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + return ::boost::algorithm::detail::find_format_copy_impl2( + Input, + Formatter, + FindResult, + Formatter(FindResult) ); + } else { + return Input; + } + } + + // replace implementation ----------------------------------------------------// + + template< + typename InputT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline void find_format_impl2( + InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult) + { + typedef find_format_store< + BOOST_STRING_TYPENAME + range_iterator<InputT>::type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + if ( !M ) + { + // Search not found - return original sequence + return; + } + + // Replace match + ::boost::algorithm::detail::replace( Input, M.begin(), M.end(), M.format_result() ); + } + + template< + typename InputT, + typename FormatterT, + typename FindResultT > + inline void find_format_impl( + InputT& Input, + FormatterT Formatter, + const FindResultT& FindResult) + { + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + ::boost::algorithm::detail::find_format_impl2( + Input, + Formatter, + FindResult, + Formatter(FindResult) ); + } + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FIND_FORMAT_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/find_format_all.hpp b/boost/boost/algorithm/string/detail/find_format_all.hpp new file mode 100644 index 0000000..52930c8 --- /dev/null +++ b/boost/boost/algorithm/string/detail/find_format_all.hpp
@@ -0,0 +1,273 @@ +// Boost string_algo library find_format_all.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP +#define BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/const_iterator.hpp> +#include <boost/range/value_type.hpp> +#include <boost/algorithm/string/detail/find_format_store.hpp> +#include <boost/algorithm/string/detail/replace_storage.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// find_format_all_copy (iterator variant) implementation ---------------------------// + + template< + typename OutputIteratorT, + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline OutputIteratorT find_format_all_copy_impl2( + OutputIteratorT Output, + const InputT& Input, + FinderT Finder, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult ) + { + typedef BOOST_STRING_TYPENAME + range_const_iterator<InputT>::type input_iterator_type; + + typedef find_format_store< + input_iterator_type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + // Initialize last match + input_iterator_type LastMatch=::boost::begin(Input); + + // Iterate through all matches + while( M ) + { + // Copy the beginning of the sequence + Output = std::copy( LastMatch, M.begin(), Output ); + // Copy formatted result + Output = std::copy( ::boost::begin(M.format_result()), ::boost::end(M.format_result()), Output ); + + // Proceed to the next match + LastMatch=M.end(); + M=Finder( LastMatch, ::boost::end(Input) ); + } + + // Copy the rest of the sequence + Output = std::copy( LastMatch, ::boost::end(Input), Output ); + + return Output; + } + + template< + typename OutputIteratorT, + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT > + inline OutputIteratorT find_format_all_copy_impl( + OutputIteratorT Output, + const InputT& Input, + FinderT Finder, + FormatterT Formatter, + const FindResultT& FindResult ) + { + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + return ::boost::algorithm::detail::find_format_all_copy_impl2( + Output, + Input, + Finder, + Formatter, + FindResult, + Formatter(FindResult) ); + } else { + return std::copy( ::boost::begin(Input), ::boost::end(Input), Output ); + } + } + + // find_format_all_copy implementation ----------------------------------------------// + + template< + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline InputT find_format_all_copy_impl2( + const InputT& Input, + FinderT Finder, + FormatterT Formatter, + const FindResultT& FindResult, + const FormatResultT& FormatResult) + { + typedef BOOST_STRING_TYPENAME + range_const_iterator<InputT>::type input_iterator_type; + + typedef find_format_store< + input_iterator_type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + // Initialize last match + input_iterator_type LastMatch=::boost::begin(Input); + + // Output temporary + InputT Output; + + // Iterate through all matches + while( M ) + { + // Copy the beginning of the sequence + 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(); + M=Finder( LastMatch, ::boost::end(Input) ); + } + + // Copy the rest of the sequence + ::boost::algorithm::detail::insert( Output, ::boost::end(Output), LastMatch, ::boost::end(Input) ); + + return Output; + } + + template< + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT > + inline InputT find_format_all_copy_impl( + const InputT& Input, + FinderT Finder, + FormatterT Formatter, + const FindResultT& FindResult) + { + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + return ::boost::algorithm::detail::find_format_all_copy_impl2( + Input, + Finder, + Formatter, + FindResult, + Formatter(FindResult) ); + } else { + return Input; + } + } + + // find_format_all implementation ------------------------------------------------// + + template< + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT, + typename FormatResultT > + inline void find_format_all_impl2( + InputT& Input, + FinderT Finder, + FormatterT Formatter, + FindResultT FindResult, + FormatResultT FormatResult) + { + typedef BOOST_STRING_TYPENAME + range_iterator<InputT>::type input_iterator_type; + typedef find_format_store< + input_iterator_type, + FormatterT, + FormatResultT > store_type; + + // Create store for the find result + store_type M( FindResult, FormatResult, Formatter ); + + // Instantiate replacement storage + std::deque< + BOOST_STRING_TYPENAME range_value<InputT>::type> Storage; + + // Initialize replacement iterators + input_iterator_type InsertIt=::boost::begin(Input); + input_iterator_type SearchIt=::boost::begin(Input); + + while( M ) + { + // process the segment + InsertIt=process_segment( + Storage, + Input, + InsertIt, + SearchIt, + M.begin() ); + + // Adjust search iterator + SearchIt=M.end(); + + // Copy formatted replace to the storage + ::boost::algorithm::detail::copy_to_storage( Storage, M.format_result() ); + + // Find range for a next match + M=Finder( SearchIt, ::boost::end(Input) ); + } + + // process the last segment + InsertIt=::boost::algorithm::detail::process_segment( + Storage, + Input, + InsertIt, + SearchIt, + ::boost::end(Input) ); + + if ( Storage.empty() ) + { + // Truncate input + ::boost::algorithm::detail::erase( Input, InsertIt, ::boost::end(Input) ); + } + else + { + // Copy remaining data to the end of input + ::boost::algorithm::detail::insert( Input, ::boost::end(Input), Storage.begin(), Storage.end() ); + } + } + + template< + typename InputT, + typename FinderT, + typename FormatterT, + typename FindResultT > + inline void find_format_all_impl( + InputT& Input, + FinderT Finder, + FormatterT Formatter, + FindResultT FindResult) + { + if( ::boost::algorithm::detail::check_find_result(Input, FindResult) ) { + ::boost::algorithm::detail::find_format_all_impl2( + Input, + Finder, + Formatter, + FindResult, + Formatter(FindResult) ); + } + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FIND_FORMAT_ALL_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/find_format_store.hpp b/boost/boost/algorithm/string/detail/find_format_store.hpp new file mode 100644 index 0000000..b9f4a88 --- /dev/null +++ b/boost/boost/algorithm/string/detail/find_format_store.hpp
@@ -0,0 +1,89 @@ +// Boost string_algo library find_format_store.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP +#define BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/range/iterator_range_core.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// temporary format and find result storage --------------------------------// + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(push) +#pragma warning(disable:4512) //assignment operator could not be generated +#endif + template< + typename ForwardIteratorT, + typename FormatterT, + typename FormatResultT > + class find_format_store : + public iterator_range<ForwardIteratorT> + { + public: + // typedefs + typedef iterator_range<ForwardIteratorT> base_type; + typedef FormatterT formatter_type; + typedef FormatResultT format_result_type; + + public: + // Construction + find_format_store( + const base_type& FindResult, + const format_result_type& FormatResult, + const formatter_type& Formatter ) : + base_type(FindResult), + m_FormatResult(FormatResult), + m_Formatter(Formatter) {} + + // Assignment + template< typename FindResultT > + find_format_store& operator=( FindResultT FindResult ) + { + iterator_range<ForwardIteratorT>::operator=(FindResult); + if( !this->empty() ) { + m_FormatResult=m_Formatter(FindResult); + } + + return *this; + } + + // Retrieve format result + const format_result_type& format_result() + { + return m_FormatResult; + } + + private: + format_result_type m_FormatResult; + const formatter_type& m_Formatter; + }; + + template<typename InputT, typename FindResultT> + bool check_find_result(InputT&, FindResultT& FindResult) + { + typedef BOOST_STRING_TYPENAME + range_const_iterator<InputT>::type input_iterator_type; + iterator_range<input_iterator_type> ResultRange(FindResult); + return !ResultRange.empty(); + } + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +#pragma warning(pop) +#endif + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FIND_FORMAT_STORE_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/find_iterator.hpp b/boost/boost/algorithm/string/detail/find_iterator.hpp new file mode 100644 index 0000000..9b78a0f --- /dev/null +++ b/boost/boost/algorithm/string/detail/find_iterator.hpp
@@ -0,0 +1,87 @@ +// Boost string_algo library find_iterator.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_ITERATOR_DETAIL_HPP +#define BOOST_STRING_FIND_ITERATOR_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/iterator/iterator_facade.hpp> +#include <boost/iterator/iterator_categories.hpp> +#include <boost/function.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// find_iterator base -----------------------------------------------// + + // Find iterator base + template<typename IteratorT> + class find_iterator_base + { + protected: + // typedefs + typedef IteratorT input_iterator_type; + typedef iterator_range<IteratorT> match_type; + typedef function2< + match_type, + input_iterator_type, + input_iterator_type> finder_type; + + protected: + // Protected construction/destruction + + // Default constructor + find_iterator_base() {}; + // Copy construction + find_iterator_base( const find_iterator_base& Other ) : + m_Finder(Other.m_Finder) {} + + // Constructor + template<typename FinderT> + find_iterator_base( FinderT Finder, int ) : + m_Finder(Finder) {} + + // Destructor + ~find_iterator_base() {} + + // Find operation + match_type do_find( + input_iterator_type Begin, + input_iterator_type End ) const + { + if (!m_Finder.empty()) + { + return m_Finder(Begin,End); + } + else + { + return match_type(End,End); + } + } + + // Check + bool is_null() const + { + return m_Finder.empty(); + } + + private: + // Finder + finder_type m_Finder; + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_FIND_ITERATOR_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/finder.hpp b/boost/boost/algorithm/string/detail/finder.hpp new file mode 100644 index 0000000..a2a9582 --- /dev/null +++ b/boost/boost/algorithm/string/detail/finder.hpp
@@ -0,0 +1,639 @@ +// Boost string_algo library finder.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FINDER_DETAIL_HPP +#define BOOST_STRING_FINDER_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/algorithm/string/constants.hpp> +#include <boost/detail/iterator.hpp> + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/empty.hpp> +#include <boost/range/as_literal.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + + +// find first functor -----------------------------------------------// + + // find a subsequence in the sequence ( functor ) + /* + Returns a pair <begin,end> marking the subsequence in the sequence. + If the find fails, functor returns <End,End> + */ + template<typename SearchIteratorT,typename PredicateT> + struct first_finderF + { + typedef SearchIteratorT search_iterator_type; + + // Construction + template< typename SearchT > + first_finderF( const SearchT& Search, PredicateT Comp ) : + m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {} + first_finderF( + search_iterator_type SearchBegin, + search_iterator_type SearchEnd, + PredicateT Comp ) : + m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef iterator_range<ForwardIteratorT> result_type; + typedef ForwardIteratorT input_iterator_type; + + // Outer loop + for(input_iterator_type OuterIt=Begin; + OuterIt!=End; + ++OuterIt) + { + // Sanity check + if( boost::empty(m_Search) ) + return result_type( End, End ); + + input_iterator_type InnerIt=OuterIt; + search_iterator_type SubstrIt=m_Search.begin(); + for(; + InnerIt!=End && SubstrIt!=m_Search.end(); + ++InnerIt,++SubstrIt) + { + if( !( m_Comp(*InnerIt,*SubstrIt) ) ) + break; + } + + // Substring matching succeeded + if ( SubstrIt==m_Search.end() ) + return result_type( OuterIt, InnerIt ); + } + + return result_type( End, End ); + } + + private: + iterator_range<search_iterator_type> m_Search; + PredicateT m_Comp; + }; + +// find last 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> + */ + template<typename SearchIteratorT, typename PredicateT> + struct last_finderF + { + typedef SearchIteratorT search_iterator_type; + typedef first_finderF< + search_iterator_type, + PredicateT> first_finder_type; + + // Construction + template< typename SearchT > + last_finderF( const SearchT& Search, PredicateT Comp ) : + m_Search(::boost::begin(Search), ::boost::end(Search)), m_Comp(Comp) {} + last_finderF( + search_iterator_type SearchBegin, + search_iterator_type SearchEnd, + PredicateT Comp ) : + m_Search(SearchBegin, SearchEnd), m_Comp(Comp) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef iterator_range<ForwardIteratorT> result_type; + + if( boost::empty(m_Search) ) + return result_type( End, End ); + + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits<ForwardIteratorT>::iterator_category category; + + return findit( Begin, End, category() ); + } + + private: + // forward iterator + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + findit( + ForwardIteratorT Begin, + ForwardIteratorT End, + std::forward_iterator_tag ) const + { + typedef iterator_range<ForwardIteratorT> result_type; + + first_finder_type first_finder( + m_Search.begin(), m_Search.end(), m_Comp ); + + result_type M=first_finder( Begin, End ); + result_type Last=M; + + while( M ) + { + Last=M; + M=first_finder( ::boost::end(M), End ); + } + + return Last; + } + + // bidirectional iterator + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + findit( + ForwardIteratorT Begin, + ForwardIteratorT End, + std::bidirectional_iterator_tag ) const + { + typedef iterator_range<ForwardIteratorT> result_type; + typedef ForwardIteratorT input_iterator_type; + + // Outer loop + for(input_iterator_type OuterIt=End; + OuterIt!=Begin; ) + { + input_iterator_type OuterIt2=--OuterIt; + + input_iterator_type InnerIt=OuterIt2; + search_iterator_type SubstrIt=m_Search.begin(); + for(; + InnerIt!=End && SubstrIt!=m_Search.end(); + ++InnerIt,++SubstrIt) + { + if( !( m_Comp(*InnerIt,*SubstrIt) ) ) + break; + } + + // Substring matching succeeded + if( SubstrIt==m_Search.end() ) + return result_type( OuterIt2, InnerIt ); + } + + return result_type( End, End ); + } + + private: + iterator_range<search_iterator_type> m_Search; + PredicateT m_Comp; + }; + +// find n-th functor -----------------------------------------------// + + // find the n-th match of a subsequence in the sequence ( functor ) + /* + Returns a pair <begin,end> marking the subsequence in the sequence. + If the find fails, returns <End,End> + */ + template<typename SearchIteratorT, typename PredicateT> + struct nth_finderF + { + typedef SearchIteratorT search_iterator_type; + typedef first_finderF< + search_iterator_type, + PredicateT> first_finder_type; + typedef last_finderF< + search_iterator_type, + PredicateT> last_finder_type; + + // Construction + template< typename SearchT > + nth_finderF( + const SearchT& Search, + int Nth, + PredicateT Comp) : + m_Search(::boost::begin(Search), ::boost::end(Search)), + m_Nth(Nth), + m_Comp(Comp) {} + nth_finderF( + search_iterator_type SearchBegin, + search_iterator_type SearchEnd, + int Nth, + PredicateT Comp) : + m_Search(SearchBegin, SearchEnd), + m_Nth(Nth), + m_Comp(Comp) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + if(m_Nth>=0) + { + return find_forward(Begin, End, m_Nth); + } + else + { + return find_backward(Begin, End, -m_Nth); + } + + } + + private: + // Implementation helpers + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + find_forward( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N) const + { + typedef iterator_range<ForwardIteratorT> result_type; + + // Sanity check + if( boost::empty(m_Search) ) + return result_type( End, End ); + + // Instantiate find functor + first_finder_type first_finder( + m_Search.begin(), m_Search.end(), m_Comp ); + + result_type M( Begin, Begin ); + + for( unsigned int n=0; n<=N; ++n ) + { + // find next match + M=first_finder( ::boost::end(M), End ); + + if ( !M ) + { + // Subsequence not found, return + return M; + } + } + + return M; + } + + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + find_backward( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N) const + { + typedef iterator_range<ForwardIteratorT> result_type; + + // Sanity check + if( boost::empty(m_Search) ) + return result_type( End, End ); + + // Instantiate find functor + last_finder_type last_finder( + m_Search.begin(), m_Search.end(), m_Comp ); + + result_type M( End, End ); + + for( unsigned int n=1; n<=N; ++n ) + { + // find next match + M=last_finder( Begin, ::boost::begin(M) ); + + if ( !M ) + { + // Subsequence not found, return + return M; + } + } + + return M; + } + + + private: + iterator_range<search_iterator_type> m_Search; + int m_Nth; + PredicateT m_Comp; + }; + +// find head/tail implementation helpers ---------------------------// + + template<typename ForwardIteratorT> + iterator_range<ForwardIteratorT> + find_head_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::forward_iterator_tag ) + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range<ForwardIteratorT> result_type; + + input_iterator_type It=Begin; + for( + unsigned int Index=0; + Index<N && It!=End; ++Index,++It ) {}; + + return result_type( Begin, It ); + } + + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + find_head_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::random_access_iterator_tag ) + { + typedef iterator_range<ForwardIteratorT> result_type; + + if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) ) + return result_type( Begin, End ); + + return result_type(Begin,Begin+N); + } + + // Find head implementation + template<typename ForwardIteratorT> + iterator_range<ForwardIteratorT> + find_head_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N ) + { + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits<ForwardIteratorT>::iterator_category category; + + return ::boost::algorithm::detail::find_head_impl( Begin, End, N, category() ); + } + + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + find_tail_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::forward_iterator_tag ) + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range<ForwardIteratorT> result_type; + + unsigned int Index=0; + input_iterator_type It=Begin; + input_iterator_type It2=Begin; + + // Advance It2 by N increments + for( Index=0; Index<N && It2!=End; ++Index,++It2 ) {}; + + // Advance It, It2 to the end + for(; It2!=End; ++It,++It2 ) {}; + + return result_type( It, It2 ); + } + + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + find_tail_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::bidirectional_iterator_tag ) + { + typedef ForwardIteratorT input_iterator_type; + typedef iterator_range<ForwardIteratorT> result_type; + + input_iterator_type It=End; + for( + unsigned int Index=0; + Index<N && It!=Begin; ++Index,--It ) {}; + + return result_type( It, End ); + } + + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + find_tail_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N, + std::random_access_iterator_tag ) + { + typedef iterator_range<ForwardIteratorT> result_type; + + if ( (End<=Begin) || ( static_cast<unsigned int>(End-Begin) < N ) ) + return result_type( Begin, End ); + + return result_type( End-N, End ); + } + + // Operation + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + find_tail_impl( + ForwardIteratorT Begin, + ForwardIteratorT End, + unsigned int N ) + { + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits<ForwardIteratorT>::iterator_category category; + + return ::boost::algorithm::detail::find_tail_impl( Begin, End, N, category() ); + } + + + +// find head functor -----------------------------------------------// + + + // find a head in the sequence ( functor ) + /* + This functor find a head of the specified range. For + a specified N, the head is a subsequence of N starting + elements of the range. + */ + struct head_finderF + { + // Construction + head_finderF( int N ) : m_N(N) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + if(m_N>=0) + { + return ::boost::algorithm::detail::find_head_impl( Begin, End, m_N ); + } + else + { + iterator_range<ForwardIteratorT> Res= + ::boost::algorithm::detail::find_tail_impl( Begin, End, -m_N ); + + return ::boost::make_iterator_range(Begin, Res.begin()); + } + } + + private: + int m_N; + }; + +// find tail functor -----------------------------------------------// + + + // find a tail in the sequence ( functor ) + /* + This functor find a tail of the specified range. For + a specified N, the head is a subsequence of N starting + elements of the range. + */ + struct tail_finderF + { + // Construction + tail_finderF( int N ) : m_N(N) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + if(m_N>=0) + { + return ::boost::algorithm::detail::find_tail_impl( Begin, End, m_N ); + } + else + { + iterator_range<ForwardIteratorT> Res= + ::boost::algorithm::detail::find_head_impl( Begin, End, -m_N ); + + return ::boost::make_iterator_range(Res.end(), End); + } + } + + private: + int m_N; + }; + +// find token functor -----------------------------------------------// + + // find a token in a sequence ( functor ) + /* + This find functor finds a token specified be a predicate + in a sequence. It is equivalent of std::find algorithm, + with an exception that it return range instead of a single + iterator. + + If bCompress is set to true, adjacent matching tokens are + concatenated into one match. + */ + template< typename PredicateT > + struct token_finderF + { + // Construction + token_finderF( + PredicateT Pred, + token_compress_mode_type eCompress=token_compress_off ) : + m_Pred(Pred), m_eCompress(eCompress) {} + + // Operation + template< typename ForwardIteratorT > + iterator_range<ForwardIteratorT> + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef iterator_range<ForwardIteratorT> result_type; + + ForwardIteratorT It=std::find_if( Begin, End, m_Pred ); + + if( It==End ) + { + return result_type( End, End ); + } + else + { + ForwardIteratorT It2=It; + + if( m_eCompress==token_compress_on ) + { + // Find first non-matching character + while( It2!=End && m_Pred(*It2) ) ++It2; + } + else + { + // Advance by one position + ++It2; + } + + return result_type( It, It2 ); + } + } + + private: + PredicateT m_Pred; + token_compress_mode_type m_eCompress; + }; + +// find range functor -----------------------------------------------// + + // find a range in the sequence ( functor ) + /* + This functor actually does not perform any find operation. + It always returns given iterator range as a result. + */ + template<typename ForwardIterator1T> + struct range_finderF + { + typedef ForwardIterator1T input_iterator_type; + typedef iterator_range<input_iterator_type> result_type; + + // Construction + range_finderF( + input_iterator_type Begin, + input_iterator_type End ) : m_Range(Begin, End) {} + + range_finderF(const iterator_range<input_iterator_type>& Range) : + m_Range(Range) {} + + // Operation + template< typename ForwardIterator2T > + iterator_range<ForwardIterator2T> + operator()( + ForwardIterator2T, + ForwardIterator2T ) const + { +#if BOOST_WORKAROUND( __MWERKS__, <= 0x3003 ) + return iterator_range<const ForwardIterator2T>(this->m_Range); +#else + return m_Range; +#endif + } + + private: + iterator_range<input_iterator_type> m_Range; + }; + + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FINDER_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/finder_regex.hpp b/boost/boost/algorithm/string/detail/finder_regex.hpp new file mode 100644 index 0000000..9cb01cf --- /dev/null +++ b/boost/boost/algorithm/string/detail/finder_regex.hpp
@@ -0,0 +1,122 @@ +// Boost string_algo library find_regex.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FINDER_REGEX_DETAIL_HPP +#define BOOST_STRING_FINDER_REGEX_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/regex.hpp> + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// regex find functor -----------------------------------------------// + + // regex search result + template<typename IteratorT> + struct regex_search_result : + public iterator_range<IteratorT> + { + typedef regex_search_result<IteratorT> type; + typedef iterator_range<IteratorT> base_type; + typedef BOOST_STRING_TYPENAME base_type::value_type value_type; + typedef BOOST_STRING_TYPENAME base_type::difference_type difference_type; + typedef BOOST_STRING_TYPENAME base_type::const_iterator const_iterator; + typedef BOOST_STRING_TYPENAME base_type::iterator iterator; + typedef boost::match_results<iterator> match_results_type; + + // Construction + + // Construction from the match result + regex_search_result( const match_results_type& MatchResults ) : + base_type( MatchResults[0].first, MatchResults[0].second ), + m_MatchResults( MatchResults ) {} + + // Construction of empty match. End iterator has to be specified + regex_search_result( IteratorT End ) : + base_type( End, End ) {} + + regex_search_result( const regex_search_result& Other ) : + base_type( Other.begin(), Other.end() ), + m_MatchResults( Other.m_MatchResults ) {} + + // Assignment + regex_search_result& operator=( const regex_search_result& Other ) + { + base_type::operator=( Other ); + m_MatchResults=Other.m_MatchResults; + return *this; + } + + // Match result retrieval + const match_results_type& match_results() const + { + return m_MatchResults; + } + + private: + // Saved match result + match_results_type m_MatchResults; + }; + + // find_regex + /* + Regex based search functor + */ + template<typename RegExT> + struct find_regexF + { + typedef RegExT regex_type; + typedef const RegExT& regex_reference_type; + + // Construction + find_regexF( regex_reference_type Rx, match_flag_type MatchFlags = match_default ) : + m_Rx(Rx), m_MatchFlags(MatchFlags) {} + + // Operation + template< typename ForwardIteratorT > + regex_search_result<ForwardIteratorT> + operator()( + ForwardIteratorT Begin, + ForwardIteratorT End ) const + { + typedef ForwardIteratorT input_iterator_type; + typedef regex_search_result<ForwardIteratorT> result_type; + + // instantiate match result + match_results<input_iterator_type> result; + // search for a match + if ( ::boost::regex_search( Begin, End, result, m_Rx, m_MatchFlags ) ) + { + // construct a result + return result_type( result ); + } + else + { + // empty result + return result_type( End ); + } + } + + private: + regex_reference_type m_Rx; // Regexp + match_flag_type m_MatchFlags; // match flags + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FIND_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/formatter.hpp b/boost/boost/algorithm/string/detail/formatter.hpp new file mode 100644 index 0000000..c071822 --- /dev/null +++ b/boost/boost/algorithm/string/detail/formatter.hpp
@@ -0,0 +1,119 @@ +// Boost string_algo library formatter.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FORMATTER_DETAIL_HPP +#define BOOST_STRING_FORMATTER_DETAIL_HPP + + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/const_iterator.hpp> + +#include <boost/algorithm/string/detail/util.hpp> + +// generic replace functors -----------------------------------------------// + +namespace boost { + namespace algorithm { + namespace detail { + +// const format functor ----------------------------------------------------// + + // constant format functor + template<typename RangeT> + struct const_formatF + { + private: + typedef BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type format_iterator; + typedef iterator_range<format_iterator> result_type; + + public: + // Construction + const_formatF(const RangeT& Format) : + m_Format(::boost::begin(Format), ::boost::end(Format)) {} + + // Operation +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) + template<typename Range2T> + result_type& operator()(const Range2T&) + { + return m_Format; + } +#endif + + template<typename Range2T> + const result_type& operator()(const Range2T&) const + { + return m_Format; + } + + private: + result_type m_Format; + }; + +// identity format functor ----------------------------------------------------// + + // identity format functor + template<typename RangeT> + struct identity_formatF + { + // Operation + template< typename Range2T > + const RangeT& operator()(const Range2T& Replace) const + { + return RangeT(::boost::begin(Replace), ::boost::end(Replace)); + } + }; + +// empty format functor ( used by erase ) ------------------------------------// + + // empty format functor + template< typename CharT > + struct empty_formatF + { + template< typename ReplaceT > + empty_container<CharT> operator()(const ReplaceT&) const + { + return empty_container<CharT>(); + } + }; + +// dissect format functor ----------------------------------------------------// + + // dissect format functor + template<typename FinderT> + struct dissect_formatF + { + public: + // Construction + dissect_formatF(FinderT Finder) : + m_Finder(Finder) {} + + // Operation + template<typename RangeT> + inline iterator_range< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> + operator()(const RangeT& Replace) const + { + return m_Finder(::boost::begin(Replace), ::boost::end(Replace)); + } + + private: + FinderT m_Finder; + }; + + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FORMATTER_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/formatter_regex.hpp b/boost/boost/algorithm/string/detail/formatter_regex.hpp new file mode 100644 index 0000000..5f26407 --- /dev/null +++ b/boost/boost/algorithm/string/detail/formatter_regex.hpp
@@ -0,0 +1,61 @@ +// Boost string_algo library formatter_regex.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FORMATTER_REGEX_DETAIL_HPP +#define BOOST_STRING_FORMATTER_REGEX_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <string> +#include <boost/regex.hpp> +#include <boost/algorithm/string/detail/finder_regex.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// regex format functor -----------------------------------------// + + // regex format functor + template<typename StringT> + struct regex_formatF + { + private: + typedef StringT result_type; + typedef BOOST_STRING_TYPENAME StringT::value_type char_type; + + public: + // Construction + regex_formatF( const StringT& Fmt, match_flag_type Flags=format_default ) : + m_Fmt(Fmt), m_Flags( Flags ) {} + + template<typename InputIteratorT> + result_type operator()( + const regex_search_result<InputIteratorT>& Replace ) const + { + if ( Replace.empty() ) + { + return result_type(); + } + else + { + return Replace.match_results().format( m_Fmt, m_Flags ); + } + } + private: + const StringT& m_Fmt; + match_flag_type m_Flags; + }; + + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_FORMATTER_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/predicate.hpp b/boost/boost/algorithm/string/detail/predicate.hpp new file mode 100644 index 0000000..5acf3cc --- /dev/null +++ b/boost/boost/algorithm/string/detail/predicate.hpp
@@ -0,0 +1,77 @@ +// Boost string_algo library predicate.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_PREDICATE_DETAIL_HPP +#define BOOST_STRING_PREDICATE_DETAIL_HPP + +#include <iterator> +#include <boost/algorithm/string/find.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// ends_with predicate implementation ----------------------------------// + + template< + typename ForwardIterator1T, + typename ForwardIterator2T, + typename PredicateT> + inline bool ends_with_iter_select( + ForwardIterator1T Begin, + ForwardIterator1T End, + ForwardIterator2T SubBegin, + ForwardIterator2T SubEnd, + PredicateT Comp, + std::bidirectional_iterator_tag) + { + ForwardIterator1T it=End; + ForwardIterator2T pit=SubEnd; + for(;it!=Begin && pit!=SubBegin;) + { + if( !(Comp(*(--it),*(--pit))) ) + return false; + } + + return pit==SubBegin; + } + + template< + typename ForwardIterator1T, + typename ForwardIterator2T, + typename PredicateT> + inline bool ends_with_iter_select( + ForwardIterator1T Begin, + ForwardIterator1T End, + ForwardIterator2T SubBegin, + ForwardIterator2T SubEnd, + PredicateT Comp, + std::forward_iterator_tag) + { + if ( SubBegin==SubEnd ) + { + // empty subsequence check + return true; + } + + iterator_range<ForwardIterator1T> Result + =last_finder( + ::boost::make_iterator_range(SubBegin, SubEnd), + Comp)(Begin, End); + + return !Result.empty() && Result.end()==End; + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_PREDICATE_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/replace_storage.hpp b/boost/boost/algorithm/string/detail/replace_storage.hpp new file mode 100644 index 0000000..db35e4c --- /dev/null +++ b/boost/boost/algorithm/string/detail/replace_storage.hpp
@@ -0,0 +1,159 @@ +// Boost string_algo library replace_storage.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP +#define BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <algorithm> +#include <boost/mpl/bool.hpp> +#include <boost/algorithm/string/sequence_traits.hpp> +#include <boost/algorithm/string/detail/sequence.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// storage handling routines -----------------------------------------------// + + template< typename StorageT, typename OutputIteratorT > + inline OutputIteratorT move_from_storage( + StorageT& Storage, + OutputIteratorT DestBegin, + OutputIteratorT DestEnd ) + { + OutputIteratorT OutputIt=DestBegin; + + while( !Storage.empty() && OutputIt!=DestEnd ) + { + *OutputIt=Storage.front(); + Storage.pop_front(); + ++OutputIt; + } + + return OutputIt; + } + + template< typename StorageT, typename WhatT > + inline void copy_to_storage( + StorageT& Storage, + const WhatT& What ) + { + Storage.insert( Storage.end(), ::boost::begin(What), ::boost::end(What) ); + } + + +// process segment routine -----------------------------------------------// + + template< bool HasStableIterators > + struct process_segment_helper + { + // Optimized version of process_segment for generic sequence + template< + typename StorageT, + typename InputT, + typename ForwardIteratorT > + ForwardIteratorT operator()( + StorageT& Storage, + InputT& /*Input*/, + ForwardIteratorT InsertIt, + ForwardIteratorT SegmentBegin, + ForwardIteratorT SegmentEnd ) + { + // Copy data from the storage until the beginning of the segment + ForwardIteratorT It=::boost::algorithm::detail::move_from_storage( Storage, InsertIt, SegmentBegin ); + + // 3 cases are possible : + // a) Storage is empty, It==SegmentBegin + // b) Storage is empty, It!=SegmentBegin + // c) Storage is not empty + + if( Storage.empty() ) + { + if( It==SegmentBegin ) + { + // Case a) everything is grand, just return end of segment + return SegmentEnd; + } + else + { + // Case b) move the segment backwards + return std::copy( SegmentBegin, SegmentEnd, It ); + } + } + else + { + // Case c) -> shift the segment to the left and keep the overlap in the storage + while( It!=SegmentEnd ) + { + // Store value into storage + Storage.push_back( *It ); + // Get the top from the storage and put it here + *It=Storage.front(); + Storage.pop_front(); + + // Advance + ++It; + } + + return It; + } + } + }; + + template<> + struct process_segment_helper< true > + { + // Optimized version of process_segment for list-like sequence + template< + typename StorageT, + typename InputT, + typename ForwardIteratorT > + ForwardIteratorT operator()( + StorageT& Storage, + InputT& Input, + ForwardIteratorT InsertIt, + ForwardIteratorT SegmentBegin, + ForwardIteratorT SegmentEnd ) + + { + // Call replace to do the job + ::boost::algorithm::detail::replace( Input, InsertIt, SegmentBegin, Storage ); + // Empty the storage + Storage.clear(); + // Iterators were not changed, simply return the end of segment + return SegmentEnd; + } + }; + + // Process one segment in the replace_all algorithm + template< + typename StorageT, + typename InputT, + typename ForwardIteratorT > + inline ForwardIteratorT process_segment( + StorageT& Storage, + InputT& Input, + ForwardIteratorT InsertIt, + ForwardIteratorT SegmentBegin, + ForwardIteratorT SegmentEnd ) + { + return + process_segment_helper< + has_stable_iterators<InputT>::value>()( + Storage, Input, InsertIt, SegmentBegin, SegmentEnd ); + } + + + } // namespace detail + } // namespace algorithm +} // namespace boost + +#endif // BOOST_STRING_REPLACE_STORAGE_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/sequence.hpp b/boost/boost/algorithm/string/detail/sequence.hpp new file mode 100644 index 0000000..dc47409 --- /dev/null +++ b/boost/boost/algorithm/string/detail/sequence.hpp
@@ -0,0 +1,200 @@ +// Boost string_algo library sequence.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_DETAIL_SEQUENCE_HPP +#define BOOST_STRING_DETAIL_SEQUENCE_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/logical.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> + +#include <boost/algorithm/string/sequence_traits.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// insert helpers -------------------------------------------------// + + template< typename InputT, typename ForwardIteratorT > + inline void insert( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator At, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + Input.insert( At, Begin, End ); + } + + template< typename InputT, typename InsertT > + inline void insert( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator At, + const InsertT& Insert ) + { + ::boost::algorithm::detail::insert( Input, At, ::boost::begin(Insert), ::boost::end(Insert) ); + } + +// erase helper ---------------------------------------------------// + + // Erase a range in the sequence + /* + Returns the iterator pointing just after the erase subrange + */ + template< typename InputT > + inline typename InputT::iterator erase( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To ) + { + return Input.erase( From, To ); + } + +// replace helper implementation ----------------------------------// + + // Optimized version of replace for generic sequence containers + // Assumption: insert and erase are expensive + template< bool HasConstTimeOperations > + struct replace_const_time_helper + { + template< typename InputT, typename ForwardIteratorT > + void operator()( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + // Copy data to the container ( as much as possible ) + ForwardIteratorT InsertIt=Begin; + BOOST_STRING_TYPENAME InputT::iterator InputIt=From; + for(; InsertIt!=End && InputIt!=To; InsertIt++, InputIt++ ) + { + *InputIt=*InsertIt; + } + + if ( InsertIt!=End ) + { + // Replace sequence is longer, insert it + Input.insert( InputIt, InsertIt, End ); + } + else + { + if ( InputIt!=To ) + { + // Replace sequence is shorter, erase the rest + Input.erase( InputIt, To ); + } + } + } + }; + + template<> + struct replace_const_time_helper< true > + { + // Const-time erase and insert methods -> use them + template< typename InputT, typename ForwardIteratorT > + void operator()( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + BOOST_STRING_TYPENAME InputT::iterator At=Input.erase( From, To ); + if ( Begin!=End ) + { + if(!Input.empty()) + { + Input.insert( At, Begin, End ); + } + else + { + Input.insert( Input.begin(), Begin, End ); + } + } + } + }; + + // No native replace method + template< bool HasNative > + struct replace_native_helper + { + template< typename InputT, typename ForwardIteratorT > + void operator()( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + replace_const_time_helper< + boost::mpl::and_< + has_const_time_insert<InputT>, + has_const_time_erase<InputT> >::value >()( + Input, From, To, Begin, End ); + } + }; + + // Container has native replace method + template<> + struct replace_native_helper< true > + { + template< typename InputT, typename ForwardIteratorT > + void operator()( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + Input.replace( From, To, Begin, End ); + } + }; + +// replace helper -------------------------------------------------// + + template< typename InputT, typename ForwardIteratorT > + inline void replace( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + replace_native_helper< has_native_replace<InputT>::value >()( + Input, From, To, Begin, End ); + } + + template< typename InputT, typename InsertT > + inline void replace( + InputT& Input, + BOOST_STRING_TYPENAME InputT::iterator From, + BOOST_STRING_TYPENAME InputT::iterator To, + const InsertT& Insert ) + { + if(From!=To) + { + ::boost::algorithm::detail::replace( Input, From, To, ::boost::begin(Insert), ::boost::end(Insert) ); + } + else + { + ::boost::algorithm::detail::insert( Input, From, ::boost::begin(Insert), ::boost::end(Insert) ); + } + } + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_DETAIL_SEQUENCE_HPP
diff --git a/boost/boost/algorithm/string/detail/trim.hpp b/boost/boost/algorithm/string/detail/trim.hpp new file mode 100644 index 0000000..1233e49 --- /dev/null +++ b/boost/boost/algorithm/string/detail/trim.hpp
@@ -0,0 +1,95 @@ +// Boost string_algo library trim.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_TRIM_DETAIL_HPP +#define BOOST_STRING_TRIM_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/detail/iterator.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// trim iterator helper -----------------------------------------------// + + template< typename ForwardIteratorT, typename PredicateT > + inline ForwardIteratorT trim_end_iter_select( + ForwardIteratorT InBegin, + ForwardIteratorT InEnd, + PredicateT IsSpace, + std::forward_iterator_tag ) + { + ForwardIteratorT TrimIt=InBegin; + + for( ForwardIteratorT It=InBegin; It!=InEnd; ++It ) + { + if ( !IsSpace(*It) ) + { + TrimIt=It; + ++TrimIt; + } + } + + return TrimIt; + } + + template< typename ForwardIteratorT, typename PredicateT > + inline ForwardIteratorT trim_end_iter_select( + ForwardIteratorT InBegin, + ForwardIteratorT InEnd, + PredicateT IsSpace, + std::bidirectional_iterator_tag ) + { + for( ForwardIteratorT It=InEnd; It!=InBegin; ) + { + if ( !IsSpace(*(--It)) ) + return ++It; + } + + return InBegin; + } + // Search for first non matching character from the beginning of the sequence + template< typename ForwardIteratorT, typename PredicateT > + inline ForwardIteratorT trim_begin( + ForwardIteratorT InBegin, + ForwardIteratorT InEnd, + PredicateT IsSpace ) + { + ForwardIteratorT It=InBegin; + for(; It!=InEnd; ++It ) + { + if (!IsSpace(*It)) + return It; + } + + return It; + } + + // Search for first non matching character from the end of the sequence + template< typename ForwardIteratorT, typename PredicateT > + inline ForwardIteratorT trim_end( + ForwardIteratorT InBegin, + ForwardIteratorT InEnd, + PredicateT IsSpace ) + { + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits<ForwardIteratorT>::iterator_category category; + + return ::boost::algorithm::detail::trim_end_iter_select( InBegin, InEnd, IsSpace, category() ); + } + + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_TRIM_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/detail/util.hpp b/boost/boost/algorithm/string/detail/util.hpp new file mode 100644 index 0000000..cf4a8b1 --- /dev/null +++ b/boost/boost/algorithm/string/detail/util.hpp
@@ -0,0 +1,106 @@ +// Boost string_algo library util.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_UTIL_DETAIL_HPP +#define BOOST_STRING_UTIL_DETAIL_HPP + +#include <boost/algorithm/string/config.hpp> +#include <functional> +#include <boost/range/iterator_range_core.hpp> + +namespace boost { + namespace algorithm { + namespace detail { + +// empty container -----------------------------------------------// + + // empty_container + /* + This class represents always empty container, + containing elements of type CharT. + + It is supposed to be used in a const version only + */ + template< typename CharT > + struct empty_container + { + typedef empty_container<CharT> type; + typedef CharT value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type& reference; + typedef const value_type& const_reference; + typedef const value_type* iterator; + typedef const value_type* const_iterator; + + + // Operations + const_iterator begin() const + { + return reinterpret_cast<const_iterator>(0); + } + + const_iterator end() const + { + return reinterpret_cast<const_iterator>(0); + } + + bool empty() const + { + return false; + } + + size_type size() const + { + return 0; + } + }; + +// bounded copy algorithm -----------------------------------------------// + + // Bounded version of the std::copy algorithm + template<typename InputIteratorT, typename OutputIteratorT> + inline OutputIteratorT bounded_copy( + InputIteratorT First, + InputIteratorT Last, + OutputIteratorT DestFirst, + OutputIteratorT DestLast ) + { + InputIteratorT InputIt=First; + OutputIteratorT OutputIt=DestFirst; + for(; InputIt!=Last && OutputIt!=DestLast; InputIt++, OutputIt++ ) + { + *OutputIt=*InputIt; + } + + return OutputIt; + } + +// iterator range utilities -----------------------------------------// + + // copy range functor + template< + typename SeqT, + typename IteratorT=BOOST_STRING_TYPENAME SeqT::const_iterator > + struct copy_iterator_rangeF : + public std::unary_function< iterator_range<IteratorT>, SeqT > + { + SeqT operator()( const iterator_range<IteratorT>& Range ) const + { + return copy_range<SeqT>(Range); + } + }; + + } // namespace detail + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_UTIL_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/erase.hpp b/boost/boost/algorithm/string/erase.hpp new file mode 100644 index 0000000..6883790 --- /dev/null +++ b/boost/boost/algorithm/string/erase.hpp
@@ -0,0 +1,844 @@ +// Boost string_algo library erase.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_ERASE_HPP +#define BOOST_STRING_ERASE_HPP + +#include <boost/algorithm/string/config.hpp> + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/const_iterator.hpp> + +#include <boost/algorithm/string/find_format.hpp> +#include <boost/algorithm/string/finder.hpp> +#include <boost/algorithm/string/formatter.hpp> + +/*! \file + Defines various erase algorithms. Each algorithm removes + part(s) of the input according to a searching criteria. +*/ + +namespace boost { + namespace algorithm { + +// erase_range -------------------------------------------------------// + + //! Erase range algorithm + /*! + Remove the given range from the input. The result is a modified copy of + the input. It is returned as a sequence or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input sequence + \param SearchRange A range in the input to be removed + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template<typename OutputIteratorT, typename RangeT> + inline OutputIteratorT erase_range_copy( + OutputIteratorT Output, + const RangeT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type>& SearchRange ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::range_finder(SearchRange), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase range algorithm + /*! + \overload + */ + template<typename SequenceT> + inline SequenceT erase_range_copy( + const SequenceT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_const_iterator<SequenceT>::type>& SearchRange ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::range_finder(SearchRange), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase range algorithm + /*! + Remove the given range from the input. + The input sequence is modified in-place. + + \param Input An input sequence + \param SearchRange A range in the input to be removed + */ + template<typename SequenceT> + inline void erase_range( + SequenceT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_iterator<SequenceT>::type>& SearchRange ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::range_finder(SearchRange), + ::boost::algorithm::empty_formatter(Input) ); + } + +// erase_first --------------------------------------------------------// + + //! Erase first algorithm + /*! + Remove the first occurrence of the substring from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT erase_first_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase first algorithm + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT erase_first_copy( + const SequenceT& Input, + const RangeT& Search ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase first algorithm + /*! + Remove the first occurrence of the substring from the input. + The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for. + */ + template<typename SequenceT, typename RangeT> + inline void erase_first( + SequenceT& Input, + const RangeT& Search ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::empty_formatter(Input) ); + } + +// erase_first ( case insensitive ) ------------------------------------// + + //! Erase first algorithm ( case insensitive ) + /*! + Remove the first occurrence of the substring from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT ierase_first_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase first algorithm ( case insensitive ) + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT ierase_first_copy( + const SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase first algorithm ( case insensitive ) + /*! + Remove the first occurrence of the substring from the input. + The input sequence is modified in-place. Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + */ + template<typename SequenceT, typename RangeT> + inline void ierase_first( + SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + +// erase_last --------------------------------------------------------// + + //! Erase last algorithm + /*! + Remove the last occurrence of the substring from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT erase_last_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::last_finder(Search), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase last algorithm + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT erase_last_copy( + const SequenceT& Input, + const RangeT& Search ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::last_finder(Search), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase last algorithm + /*! + Remove the last occurrence of the substring from the input. + The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + */ + template<typename SequenceT, typename RangeT> + inline void erase_last( + SequenceT& Input, + const RangeT& Search ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::last_finder(Search), + ::boost::algorithm::empty_formatter(Input) ); + } + +// erase_last ( case insensitive ) ------------------------------------// + + //! Erase last algorithm ( case insensitive ) + /*! + Remove the last occurrence of the substring from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT ierase_last_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::last_finder(Search, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase last algorithm ( case insensitive ) + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT ierase_last_copy( + const SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::last_finder(Search, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase last algorithm ( case insensitive ) + /*! + Remove the last occurrence of the substring from the input. + The input sequence is modified in-place. Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + */ + template<typename SequenceT, typename RangeT> + inline void ierase_last( + SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::last_finder(Search, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + +// erase_nth --------------------------------------------------------------------// + + //! Erase nth algorithm + /*! + Remove the Nth occurrence of the substring in the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT erase_nth_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + int Nth ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::nth_finder(Search, Nth), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase nth algorithm + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT erase_nth_copy( + const SequenceT& Input, + const RangeT& Search, + int Nth ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::nth_finder(Search, Nth), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase nth algorithm + /*! + Remove the Nth occurrence of the substring in the input. + The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for. + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + */ + template<typename SequenceT, typename RangeT> + inline void erase_nth( + SequenceT& Input, + const RangeT& Search, + int Nth ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::nth_finder(Search, Nth), + ::boost::algorithm::empty_formatter(Input) ); + } + +// erase_nth ( case insensitive ) ---------------------------------------------// + + //! Erase nth algorithm ( case insensitive ) + /*! + Remove the Nth occurrence of the substring in the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for. + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT ierase_nth_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + int Nth, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase nth algorithm + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT ierase_nth_copy( + const SequenceT& Input, + const RangeT& Search, + int Nth, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)), + empty_formatter(Input) ); + } + + //! Erase nth algorithm + /*! + Remove the Nth occurrence of the substring in the input. + The input sequence is modified in-place. Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for. + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Loc A locale used for case insensitive comparison + */ + template<typename SequenceT, typename RangeT> + inline void ierase_nth( + SequenceT& Input, + const RangeT& Search, + int Nth, + const std::locale& Loc=std::locale() ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + + +// erase_all --------------------------------------------------------// + + //! Erase all algorithm + /*! + Remove all the occurrences of the string from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + + \param Output An output iterator to which the result will be copied + \param Input An input sequence + \param Search A substring to be searched for. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT erase_all_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search ) + { + return ::boost::algorithm::find_format_all_copy( + Output, + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase all algorithm + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT erase_all_copy( + const SequenceT& Input, + const RangeT& Search ) + { + return ::boost::algorithm::find_format_all_copy( + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase all algorithm + /*! + Remove all the occurrences of the string from the input. + The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for. + */ + template<typename SequenceT, typename RangeT> + inline void erase_all( + SequenceT& Input, + const RangeT& Search ) + { + ::boost::algorithm::find_format_all( + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::empty_formatter(Input) ); + } + +// erase_all ( case insensitive ) ------------------------------------// + + //! Erase all algorithm ( case insensitive ) + /*! + Remove all the occurrences of the string from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT ierase_all_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_all_copy( + Output, + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase all algorithm ( case insensitive ) + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT ierase_all_copy( + const SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_all_copy( + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + + //! Erase all algorithm ( case insensitive ) + /*! + Remove all the occurrences of the string from the input. + The input sequence is modified in-place. Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for. + \param Loc A locale used for case insensitive comparison + */ + template<typename SequenceT, typename RangeT> + inline void ierase_all( + SequenceT& Input, + const RangeT& Search, + const std::locale& Loc=std::locale() ) + { + ::boost::algorithm::find_format_all( + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::empty_formatter(Input) ); + } + +// erase_head --------------------------------------------------------------------// + + //! Erase head algorithm + /*! + Remove the head from the input. The head is a prefix of a sequence of given size. + If the sequence is shorter then required, the whole string is + considered to be the head. The result is a modified copy of the input. + It is returned as a sequence or copied to the output iterator. + + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param N Length of the head. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT> + inline OutputIteratorT erase_head_copy( + OutputIteratorT Output, + const RangeT& Input, + int N ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::head_finder(N), + ::boost::algorithm::empty_formatter( Input ) ); + } + + //! Erase head algorithm + /*! + \overload + */ + template<typename SequenceT> + inline SequenceT erase_head_copy( + const SequenceT& Input, + int N ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::head_finder(N), + ::boost::algorithm::empty_formatter( Input ) ); + } + + //! Erase head algorithm + /*! + Remove the head from the input. The head is a prefix of a sequence of given size. + If the sequence is shorter then required, the whole string is + considered to be the head. The input sequence is modified in-place. + + \param Input An input string + \param N Length of the head + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + */ + template<typename SequenceT> + inline void erase_head( + SequenceT& Input, + int N ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::head_finder(N), + ::boost::algorithm::empty_formatter( Input ) ); + } + +// erase_tail --------------------------------------------------------------------// + + //! Erase tail algorithm + /*! + Remove the tail from the input. The tail is a suffix of a sequence of given size. + If the sequence is shorter then required, the whole string is + considered to be the tail. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param N Length of the tail. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT> + inline OutputIteratorT erase_tail_copy( + OutputIteratorT Output, + const RangeT& Input, + int N ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::tail_finder(N), + ::boost::algorithm::empty_formatter( Input ) ); + } + + //! Erase tail algorithm + /*! + \overload + */ + template<typename SequenceT> + inline SequenceT erase_tail_copy( + const SequenceT& Input, + int N ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::tail_finder(N), + ::boost::algorithm::empty_formatter( Input ) ); + } + + //! Erase tail algorithm + /*! + Remove the tail from the input. The tail is a suffix of a sequence of given size. + If the sequence is shorter then required, the whole string is + considered to be the tail. The input sequence is modified in-place. + + \param Input An input string + \param N Length of the tail + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + */ + template<typename SequenceT> + inline void erase_tail( + SequenceT& Input, + int N ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::tail_finder(N), + ::boost::algorithm::empty_formatter( Input ) ); + } + + } // namespace algorithm + + // pull names into the boost namespace + using algorithm::erase_range_copy; + using algorithm::erase_range; + using algorithm::erase_first_copy; + using algorithm::erase_first; + using algorithm::ierase_first_copy; + using algorithm::ierase_first; + using algorithm::erase_last_copy; + using algorithm::erase_last; + using algorithm::ierase_last_copy; + using algorithm::ierase_last; + using algorithm::erase_nth_copy; + using algorithm::erase_nth; + using algorithm::ierase_nth_copy; + using algorithm::ierase_nth; + using algorithm::erase_all_copy; + using algorithm::erase_all; + using algorithm::ierase_all_copy; + using algorithm::ierase_all; + using algorithm::erase_head_copy; + using algorithm::erase_head; + using algorithm::erase_tail_copy; + using algorithm::erase_tail; + +} // namespace boost + + +#endif // BOOST_ERASE_HPP
diff --git a/boost/boost/algorithm/string/find.hpp b/boost/boost/algorithm/string/find.hpp new file mode 100644 index 0000000..f2c2926 --- /dev/null +++ b/boost/boost/algorithm/string/find.hpp
@@ -0,0 +1,334 @@ +// Boost string_algo library find.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_HPP +#define BOOST_STRING_FIND_HPP + +#include <boost/algorithm/string/config.hpp> + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/as_literal.hpp> + +#include <boost/algorithm/string/finder.hpp> +#include <boost/algorithm/string/compare.hpp> +#include <boost/algorithm/string/constants.hpp> + +/*! \file + Defines a set of find algorithms. The algorithms are searching + for a substring of the input. The result is given as an \c iterator_range + delimiting the substring. +*/ + +namespace boost { + namespace algorithm { + +// Generic find -----------------------------------------------// + + //! Generic find algorithm + /*! + Search the input using the given finder. + + \param Input A string which will be searched. + \param Finder Finder object used for searching. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + */ + template<typename RangeT, typename FinderT> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<RangeT>::type> + find( + RangeT& Input, + const FinderT& Finder) + { + iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input)); + + return Finder(::boost::begin(lit_input),::boost::end(lit_input)); + } + +// find_first -----------------------------------------------// + + //! Find first algorithm + /*! + Search for the first occurrence of the substring in the input. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<Range1T>::type> + find_first( + Range1T& Input, + const Range2T& Search) + { + return ::boost::algorithm::find(Input, ::boost::algorithm::first_finder(Search)); + } + + //! Find first algorithm ( case insensitive ) + /*! + Search for the first occurrence of the substring in the input. + Searching is case insensitive. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \param Loc A locale used for case insensitive comparison + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<Range1T>::type> + ifind_first( + Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::find(Input, ::boost::algorithm::first_finder(Search,is_iequal(Loc))); + } + +// find_last -----------------------------------------------// + + //! Find last algorithm + /*! + Search for the last occurrence of the substring in the input. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<Range1T>::type> + find_last( + Range1T& Input, + const Range2T& Search) + { + return ::boost::algorithm::find(Input, ::boost::algorithm::last_finder(Search)); + } + + //! Find last algorithm ( case insensitive ) + /*! + Search for the last match a string in the input. + Searching is case insensitive. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \param Loc A locale used for case insensitive comparison + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<Range1T>::type> + ifind_last( + Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::find(Input, ::boost::algorithm::last_finder(Search, is_iequal(Loc))); + } + +// find_nth ----------------------------------------------------------------------// + + //! Find n-th algorithm + /*! + Search for the n-th (zero-indexed) occurrence of the substring in the + input. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \param Nth An index (zero-indexed) of the match to be found. + For negative N, the matches are counted from the end of string. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + */ + template<typename Range1T, typename Range2T> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<Range1T>::type> + find_nth( + Range1T& Input, + const Range2T& Search, + int Nth) + { + return ::boost::algorithm::find(Input, ::boost::algorithm::nth_finder(Search,Nth)); + } + + //! Find n-th algorithm ( case insensitive ). + /*! + Search for the n-th (zero-indexed) occurrence of the substring in the + input. Searching is case insensitive. + + \param Input A string which will be searched. + \param Search A substring to be searched for. + \param Nth An index (zero-indexed) of the match to be found. + For negative N, the matches are counted from the end of string. + \param Loc A locale used for case insensitive comparison + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<Range1T>::type> + ifind_nth( + Range1T& Input, + const Range2T& Search, + int Nth, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::find(Input, ::boost::algorithm::nth_finder(Search,Nth,is_iequal(Loc))); + } + +// find_head ----------------------------------------------------------------------// + + //! Find head algorithm + /*! + Get the head of the input. Head is a prefix of the string of the + given size. If the input is shorter then required, whole input 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, at most size(Input)-|N| characters are extracted. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c Range1T::iterator or + \c Range1T::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template<typename RangeT> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<RangeT>::type> + find_head( + RangeT& Input, + int N) + { + return ::boost::algorithm::find(Input, ::boost::algorithm::head_finder(N)); + } + +// find_tail ----------------------------------------------------------------------// + + //! 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 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, at most size(Input)-|N| characters are extracted. + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + + + \note This function provides the strong exception-safety guarantee + */ + template<typename RangeT> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<RangeT>::type> + find_tail( + RangeT& Input, + int N) + { + return ::boost::algorithm::find(Input, ::boost::algorithm::tail_finder(N)); + } + +// find_token --------------------------------------------------------------------// + + //! Find token algorithm + /*! + Look for a given token in the string. Token is a character that matches the + given predicate. + If the "token compress mode" is enabled, adjacent tokens are considered to be one match. + + \param Input A input string. + \param Pred A unary predicate to identify a token + \param eCompress Enable/Disable compressing of adjacent tokens + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template<typename RangeT, typename PredicateT> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<RangeT>::type> + find_token( + RangeT& Input, + PredicateT Pred, + token_compress_mode_type eCompress=token_compress_off) + { + return ::boost::algorithm::find(Input, ::boost::algorithm::token_finder(Pred, eCompress)); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::find; + using algorithm::find_first; + using algorithm::ifind_first; + using algorithm::find_last; + using algorithm::ifind_last; + using algorithm::find_nth; + using algorithm::ifind_nth; + using algorithm::find_head; + using algorithm::find_tail; + using algorithm::find_token; + +} // namespace boost + + +#endif // BOOST_STRING_FIND_HPP
diff --git a/boost/boost/algorithm/string/find_format.hpp b/boost/boost/algorithm/string/find_format.hpp new file mode 100644 index 0000000..0e84a4e --- /dev/null +++ b/boost/boost/algorithm/string/find_format.hpp
@@ -0,0 +1,287 @@ +// Boost string_algo library find_format.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_FORMAT_HPP +#define BOOST_STRING_FIND_FORMAT_HPP + +#include <deque> +#include <boost/detail/iterator.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/const_iterator.hpp> +#include <boost/range/as_literal.hpp> + +#include <boost/algorithm/string/concept.hpp> +#include <boost/algorithm/string/detail/find_format.hpp> +#include <boost/algorithm/string/detail/find_format_all.hpp> + +/*! \file + Defines generic replace algorithms. Each algorithm replaces + part(s) of the input. The part to be replaced is looked up using a Finder object. + Result of finding is then used by a Formatter object to generate the replacement. +*/ + +namespace boost { + namespace algorithm { + +// generic replace -----------------------------------------------------------------// + + //! Generic replace algorithm + /*! + Use the Finder to search for a substring. Use the Formatter to format + this substring and replace it in the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input sequence + \param Finder A Finder object used to search for a match to be replaced + \param Formatter A Formatter object used to format a match + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename FinderT, + typename FormatterT> + inline OutputIteratorT find_format_copy( + OutputIteratorT Output, + const RangeT& Input, + FinderT Finder, + FormatterT Formatter ) + { + // Concept check + BOOST_CONCEPT_ASSERT(( + FinderConcept< + FinderT, + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> + )); + BOOST_CONCEPT_ASSERT(( + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> + )); + + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input)); + + return detail::find_format_copy_impl( + Output, + lit_input, + Formatter, + Finder( ::boost::begin(lit_input), ::boost::end(lit_input) ) ); + } + + //! Generic replace algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename FinderT, + typename FormatterT> + inline SequenceT find_format_copy( + const SequenceT& Input, + FinderT Finder, + FormatterT Formatter ) + { + // Concept check + BOOST_CONCEPT_ASSERT(( + FinderConcept< + FinderT, + BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> + )); + BOOST_CONCEPT_ASSERT(( + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> + )); + + return detail::find_format_copy_impl( + Input, + Formatter, + Finder(::boost::begin(Input), ::boost::end(Input))); + } + + //! Generic replace algorithm + /*! + Use the Finder to search for a substring. Use the Formatter to format + this substring and replace it in the input. The input is modified in-place. + + \param Input An input sequence + \param Finder A Finder object used to search for a match to be replaced + \param Formatter A Formatter object used to format a match + */ + template< + typename SequenceT, + typename FinderT, + typename FormatterT> + inline void find_format( + SequenceT& Input, + FinderT Finder, + FormatterT Formatter) + { + // Concept check + BOOST_CONCEPT_ASSERT(( + FinderConcept< + FinderT, + BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> + )); + BOOST_CONCEPT_ASSERT(( + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> + )); + + detail::find_format_impl( + Input, + Formatter, + Finder(::boost::begin(Input), ::boost::end(Input))); + } + + +// find_format_all generic ----------------------------------------------------------------// + + //! Generic replace all algorithm + /*! + Use the Finder to search for a substring. Use the Formatter to format + this substring and replace it in the input. Repeat this for all matching + substrings. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input sequence + \param Finder A Finder object used to search for a match to be replaced + \param Formatter A Formatter object used to format a match + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename FinderT, + typename FormatterT> + inline OutputIteratorT find_format_all_copy( + OutputIteratorT Output, + const RangeT& Input, + FinderT Finder, + FormatterT Formatter) + { + // Concept check + BOOST_CONCEPT_ASSERT(( + FinderConcept< + FinderT, + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> + )); + BOOST_CONCEPT_ASSERT(( + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> + )); + + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input)); + + return detail::find_format_all_copy_impl( + Output, + lit_input, + Finder, + Formatter, + Finder(::boost::begin(lit_input), ::boost::end(lit_input))); + } + + //! Generic replace all algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename FinderT, + typename FormatterT > + inline SequenceT find_format_all_copy( + const SequenceT& Input, + FinderT Finder, + FormatterT Formatter ) + { + // Concept check + BOOST_CONCEPT_ASSERT(( + FinderConcept< + FinderT, + BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> + )); + BOOST_CONCEPT_ASSERT(( + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> + )); + + return detail::find_format_all_copy_impl( + Input, + Finder, + Formatter, + Finder( ::boost::begin(Input), ::boost::end(Input) ) ); + } + + //! Generic replace all algorithm + /*! + Use the Finder to search for a substring. Use the Formatter to format + this substring and replace it in the input. Repeat this for all matching + substrings.The input is modified in-place. + + \param Input An input sequence + \param Finder A Finder object used to search for a match to be replaced + \param Formatter A Formatter object used to format a match + */ + template< + typename SequenceT, + typename FinderT, + typename FormatterT > + inline void find_format_all( + SequenceT& Input, + FinderT Finder, + FormatterT Formatter ) + { + // Concept check + BOOST_CONCEPT_ASSERT(( + FinderConcept< + FinderT, + BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> + )); + BOOST_CONCEPT_ASSERT(( + FormatterConcept< + FormatterT, + FinderT,BOOST_STRING_TYPENAME range_const_iterator<SequenceT>::type> + )); + + detail::find_format_all_impl( + Input, + Finder, + Formatter, + Finder(::boost::begin(Input), ::boost::end(Input))); + + } + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::find_format_copy; + using algorithm::find_format; + using algorithm::find_format_all_copy; + using algorithm::find_format_all; + +} // namespace boost + + +#endif // BOOST_STRING_FIND_FORMAT_HPP
diff --git a/boost/boost/algorithm/string/find_iterator.hpp b/boost/boost/algorithm/string/find_iterator.hpp new file mode 100644 index 0000000..5a52d92 --- /dev/null +++ b/boost/boost/algorithm/string/find_iterator.hpp
@@ -0,0 +1,388 @@ +// Boost string_algo library find_iterator.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2004. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FIND_ITERATOR_HPP +#define BOOST_STRING_FIND_ITERATOR_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/iterator/iterator_facade.hpp> +#include <boost/iterator/iterator_categories.hpp> + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/as_literal.hpp> + +#include <boost/algorithm/string/detail/find_iterator.hpp> + +/*! \file + Defines find iterator classes. Find iterator repeatedly applies a Finder + to the specified input string to search for matches. Dereferencing + the iterator yields the current match or a range between the last and the current + match depending on the iterator used. +*/ + +namespace boost { + namespace algorithm { + +// find_iterator -----------------------------------------------// + + //! find_iterator + /*! + Find iterator encapsulates a Finder and allows + for incremental searching in a string. + Each increment moves the iterator to the next match. + + Find iterator is a readable forward traversal iterator. + + Dereferencing the iterator yields an iterator_range delimiting + the current match. + */ + template<typename IteratorT> + class find_iterator : + public iterator_facade< + find_iterator<IteratorT>, + const iterator_range<IteratorT>, + forward_traversal_tag >, + private detail::find_iterator_base<IteratorT> + { + private: + // facade support + friend class ::boost::iterator_core_access; + + private: + // typedefs + + typedef detail::find_iterator_base<IteratorT> base_type; + typedef BOOST_STRING_TYPENAME + base_type::input_iterator_type input_iterator_type; + typedef BOOST_STRING_TYPENAME + base_type::match_type match_type; + + public: + //! Default constructor + /*! + Construct null iterator. All null iterators are equal. + + \post eof()==true + */ + find_iterator() {} + + //! Copy constructor + /*! + Construct a copy of the find_iterator + */ + find_iterator( const find_iterator& Other ) : + base_type(Other), + m_Match(Other.m_Match), + m_End(Other.m_End) {} + + //! Constructor + /*! + Construct new find_iterator for a given finder + and a range. + */ + template<typename FinderT> + find_iterator( + IteratorT Begin, + IteratorT End, + FinderT Finder ) : + detail::find_iterator_base<IteratorT>(Finder,0), + m_Match(Begin,Begin), + m_End(End) + { + increment(); + } + + //! Constructor + /*! + Construct new find_iterator for a given finder + and a range. + */ + template<typename FinderT, typename RangeT> + find_iterator( + RangeT& Col, + FinderT Finder ) : + detail::find_iterator_base<IteratorT>(Finder,0) + { + iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col)); + m_Match=::boost::make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); + m_End=::boost::end(lit_col); + + increment(); + } + + private: + // iterator operations + + // dereference + const match_type& dereference() const + { + return m_Match; + } + + // increment + void increment() + { + m_Match=this->do_find(m_Match.end(),m_End); + } + + // comparison + bool equal( const find_iterator& Other ) const + { + bool bEof=eof(); + bool bOtherEof=Other.eof(); + + return bEof || bOtherEof ? bEof==bOtherEof : + ( + m_Match==Other.m_Match && + m_End==Other.m_End + ); + } + + public: + // operations + + //! Eof check + /*! + Check the eof condition. Eof condition means that + there is nothing more to be searched i.e. find_iterator + is after the last match. + */ + bool eof() const + { + return + this->is_null() || + ( + m_Match.begin() == m_End && + m_Match.end() == m_End + ); + } + + private: + // Attributes + match_type m_Match; + input_iterator_type m_End; + }; + + //! find iterator construction helper + /*! + * Construct a find iterator to iterate through the specified string + */ + template<typename RangeT, typename FinderT> + inline find_iterator< + BOOST_STRING_TYPENAME range_iterator<RangeT>::type> + make_find_iterator( + RangeT& Collection, + FinderT Finder) + { + return find_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>( + Collection, Finder); + } + +// split iterator -----------------------------------------------// + + //! split_iterator + /*! + Split iterator encapsulates a Finder and allows + for incremental searching in a string. + Unlike the find iterator, split iterator iterates + through gaps between matches. + + Find iterator is a readable forward traversal iterator. + + Dereferencing the iterator yields an iterator_range delimiting + the current match. + */ + template<typename IteratorT> + class split_iterator : + public iterator_facade< + split_iterator<IteratorT>, + const iterator_range<IteratorT>, + forward_traversal_tag >, + private detail::find_iterator_base<IteratorT> + { + private: + // facade support + friend class ::boost::iterator_core_access; + + private: + // typedefs + + typedef detail::find_iterator_base<IteratorT> base_type; + typedef BOOST_STRING_TYPENAME + base_type::input_iterator_type input_iterator_type; + typedef BOOST_STRING_TYPENAME + base_type::match_type match_type; + + public: + //! Default constructor + /*! + Construct null iterator. All null iterators are equal. + + \post eof()==true + */ + split_iterator() : + m_Next(), + m_End(), + m_bEof(true) + {} + + //! Copy constructor + /*! + Construct a copy of the split_iterator + */ + split_iterator( const split_iterator& Other ) : + base_type(Other), + m_Match(Other.m_Match), + m_Next(Other.m_Next), + m_End(Other.m_End), + m_bEof(Other.m_bEof) + {} + + //! Constructor + /*! + Construct new split_iterator for a given finder + and a range. + */ + template<typename FinderT> + split_iterator( + IteratorT Begin, + IteratorT End, + FinderT Finder ) : + detail::find_iterator_base<IteratorT>(Finder,0), + m_Match(Begin,Begin), + m_Next(Begin), + m_End(End), + m_bEof(false) + { + // force the correct behavior for empty sequences and yield at least one token + if(Begin!=End) + { + increment(); + } + } + //! Constructor + /*! + Construct new split_iterator for a given finder + and a collection. + */ + template<typename FinderT, typename RangeT> + split_iterator( + RangeT& Col, + FinderT Finder ) : + detail::find_iterator_base<IteratorT>(Finder,0), + m_bEof(false) + { + iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_col(::boost::as_literal(Col)); + m_Match=make_iterator_range(::boost::begin(lit_col), ::boost::begin(lit_col)); + m_Next=::boost::begin(lit_col); + m_End=::boost::end(lit_col); + + // force the correct behavior for empty sequences and yield at least one token + if(m_Next!=m_End) + { + increment(); + } + } + + + private: + // iterator operations + + // dereference + const match_type& dereference() const + { + return m_Match; + } + + // increment + void increment() + { + match_type FindMatch=this->do_find( m_Next, m_End ); + + if(FindMatch.begin()==m_End && FindMatch.end()==m_End) + { + if(m_Match.end()==m_End) + { + // Mark iterator as eof + m_bEof=true; + } + } + + m_Match=match_type( m_Next, FindMatch.begin() ); + m_Next=FindMatch.end(); + } + + // comparison + bool equal( const split_iterator& Other ) const + { + bool bEof=eof(); + bool bOtherEof=Other.eof(); + + return bEof || bOtherEof ? bEof==bOtherEof : + ( + m_Match==Other.m_Match && + m_Next==Other.m_Next && + m_End==Other.m_End + ); + } + + public: + // operations + + //! Eof check + /*! + Check the eof condition. Eof condition means that + there is nothing more to be searched i.e. find_iterator + is after the last match. + */ + bool eof() const + { + return this->is_null() || m_bEof; + } + + private: + // Attributes + match_type m_Match; + input_iterator_type m_Next; + input_iterator_type m_End; + bool m_bEof; + }; + + //! split iterator construction helper + /*! + * Construct a split iterator to iterate through the specified collection + */ + template<typename RangeT, typename FinderT> + inline split_iterator< + BOOST_STRING_TYPENAME range_iterator<RangeT>::type> + make_split_iterator( + RangeT& Collection, + FinderT Finder) + { + return split_iterator<BOOST_STRING_TYPENAME range_iterator<RangeT>::type>( + Collection, Finder); + } + + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::find_iterator; + using algorithm::make_find_iterator; + using algorithm::split_iterator; + using algorithm::make_split_iterator; + +} // namespace boost + + +#endif // BOOST_STRING_FIND_ITERATOR_HPP
diff --git a/boost/boost/algorithm/string/finder.hpp b/boost/boost/algorithm/string/finder.hpp new file mode 100644 index 0000000..93f7ec3 --- /dev/null +++ b/boost/boost/algorithm/string/finder.hpp
@@ -0,0 +1,270 @@ +// Boost string_algo library finder.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FINDER_HPP +#define BOOST_STRING_FINDER_HPP + +#include <boost/algorithm/string/config.hpp> + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/const_iterator.hpp> + +#include <boost/algorithm/string/constants.hpp> +#include <boost/algorithm/string/detail/finder.hpp> +#include <boost/algorithm/string/compare.hpp> + +/*! \file + Defines Finder generators. Finder object is a functor which is able to + find a substring matching a specific criteria in the input. + Finders are used as a pluggable components for replace, find + and split facilities. This header contains generator functions + for finders provided in this library. +*/ + +namespace boost { + namespace algorithm { + +// Finder generators ------------------------------------------// + + //! "First" finder + /*! + Construct the \c first_finder. The finder searches for the first + occurrence of the string in a given input. + The result is given as an \c iterator_range delimiting the match. + + \param Search A substring to be searched for. + \param Comp An element comparison predicate + \return An instance of the \c first_finder object + */ + template<typename RangeT> + inline detail::first_finderF< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type, + is_equal> + first_finder( const RangeT& Search ) + { + return + detail::first_finderF< + BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type, + is_equal>( ::boost::as_literal(Search), is_equal() ) ; + } + + //! "First" finder + /*! + \overload + */ + template<typename RangeT,typename PredicateT> + inline detail::first_finderF< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type, + PredicateT> + first_finder( + const RangeT& Search, PredicateT Comp ) + { + return + detail::first_finderF< + BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type, + PredicateT>( ::boost::as_literal(Search), Comp ); + } + + //! "Last" finder + /*! + Construct the \c last_finder. The finder searches for the last + occurrence of the string in a given input. + The result is given as an \c iterator_range delimiting the match. + + \param Search A substring to be searched for. + \param Comp An element comparison predicate + \return An instance of the \c last_finder object + */ + template<typename RangeT> + inline detail::last_finderF< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type, + is_equal> + last_finder( const RangeT& Search ) + { + return + detail::last_finderF< + BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type, + is_equal>( ::boost::as_literal(Search), is_equal() ); + } + //! "Last" finder + /*! + \overload + */ + template<typename RangeT, typename PredicateT> + inline detail::last_finderF< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type, + PredicateT> + last_finder( const RangeT& Search, PredicateT Comp ) + { + return + detail::last_finderF< + BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type, + PredicateT>( ::boost::as_literal(Search), Comp ) ; + } + + //! "Nth" finder + /*! + Construct the \c nth_finder. The finder searches for the n-th (zero-indexed) + occurrence of the string in a given input. + The result is given as an \c iterator_range delimiting the match. + + \param Search A substring to be searched for. + \param Nth An index of the match to be find + \param Comp An element comparison predicate + \return An instance of the \c nth_finder object + */ + template<typename RangeT> + inline detail::nth_finderF< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type, + is_equal> + nth_finder( + const RangeT& Search, + int Nth) + { + return + detail::nth_finderF< + BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type, + is_equal>( ::boost::as_literal(Search), Nth, is_equal() ) ; + } + //! "Nth" finder + /*! + \overload + */ + template<typename RangeT, typename PredicateT> + inline detail::nth_finderF< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type, + PredicateT> + nth_finder( + const RangeT& Search, + int Nth, + PredicateT Comp ) + { + return + detail::nth_finderF< + BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type, + PredicateT>( ::boost::as_literal(Search), Nth, Comp ); + } + + //! "Head" finder + /*! + Construct the \c head_finder. The finder returns a head of a given + input. The head is a prefix of a string up to n elements in + size. If an input has less then n elements, whole input is + considered a head. + The result is given as an \c iterator_range delimiting the match. + + \param N The size of the head + \return An instance of the \c head_finder object + */ + inline detail::head_finderF + head_finder( int N ) + { + return detail::head_finderF(N); + } + + //! "Tail" finder + /*! + Construct the \c tail_finder. The finder returns a tail of a given + input. The tail is a suffix of a string up to n elements in + size. If an input has less then n elements, whole input is + considered a head. + The result is given as an \c iterator_range delimiting the match. + + \param N The size of the head + \return An instance of the \c tail_finder object + */ + inline detail::tail_finderF + tail_finder( int N ) + { + return detail::tail_finderF(N); + } + + //! "Token" finder + /*! + Construct the \c token_finder. The finder searches for a token + specified by a predicate. It is similar to std::find_if + algorithm, with an exception that it return a range of + instead of a single iterator. + + If "compress token mode" is enabled, adjacent matching tokens are + concatenated into one match. Thus the finder can be used to + search for continuous segments of characters satisfying the + given predicate. + + The result is given as an \c iterator_range delimiting the match. + + \param Pred An element selection predicate + \param eCompress Compress flag + \return An instance of the \c token_finder object + */ + template< typename PredicateT > + inline detail::token_finderF<PredicateT> + token_finder( + PredicateT Pred, + token_compress_mode_type eCompress=token_compress_off ) + { + return detail::token_finderF<PredicateT>( Pred, eCompress ); + } + + //! "Range" finder + /*! + Construct the \c range_finder. The finder does not perform + any operation. It simply returns the given range for + any input. + + \param Begin Beginning of the range + \param End End of the range + \param Range The range. + \return An instance of the \c range_finger object + */ + template< typename ForwardIteratorT > + inline detail::range_finderF<ForwardIteratorT> + range_finder( + ForwardIteratorT Begin, + ForwardIteratorT End ) + { + return detail::range_finderF<ForwardIteratorT>( Begin, End ); + } + + //! "Range" finder + /*! + \overload + */ + template< typename ForwardIteratorT > + inline detail::range_finderF<ForwardIteratorT> + range_finder( iterator_range<ForwardIteratorT> Range ) + { + return detail::range_finderF<ForwardIteratorT>( Range ); + } + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::first_finder; + using algorithm::last_finder; + using algorithm::nth_finder; + using algorithm::head_finder; + using algorithm::tail_finder; + using algorithm::token_finder; + using algorithm::range_finder; + +} // namespace boost + + +#endif // BOOST_STRING_FINDER_HPP
diff --git a/boost/boost/algorithm/string/formatter.hpp b/boost/boost/algorithm/string/formatter.hpp new file mode 100644 index 0000000..de8681b --- /dev/null +++ b/boost/boost/algorithm/string/formatter.hpp
@@ -0,0 +1,120 @@ +// Boost string_algo library formatter.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_FORMATTER_HPP +#define BOOST_STRING_FORMATTER_HPP + +#include <boost/detail/iterator.hpp> +#include <boost/range/value_type.hpp> +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/as_literal.hpp> + +#include <boost/algorithm/string/detail/formatter.hpp> + +/*! \file + Defines Formatter generators. Formatter is a functor which formats + a string according to given parameters. A Formatter works + in conjunction with a Finder. A Finder can provide additional information + for a specific Formatter. An example of such a cooperation is regex_finder + and regex_formatter. + + Formatters are used as pluggable components for replace facilities. + This header contains generator functions for the Formatters provided in this library. +*/ + +namespace boost { + namespace algorithm { + +// generic formatters ---------------------------------------------------------------// + + //! Constant formatter + /*! + 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 formatting + \return An instance of the \c const_formatter object. + */ + template<typename RangeT> + inline detail::const_formatF< + iterator_range< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> > + const_formatter(const RangeT& Format) + { + return detail::const_formatF< + iterator_range< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >(::boost::as_literal(Format)); + } + + //! Identity formatter + /*! + Constructs an \c identity_formatter. Identity formatter always returns + the parameter. + + \return An instance of the \c identity_formatter object. + */ + template<typename RangeT> + inline detail::identity_formatF< + iterator_range< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> > + identity_formatter() + { + return detail::identity_formatF< + iterator_range< + BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> >(); + } + + //! Empty formatter + /*! + Constructs an \c empty_formatter. Empty formatter always returns an empty + sequence. + + \param Input container used to select a correct value_type for the + resulting empty_container<>. + \return An instance of the \c empty_formatter object. + */ + template<typename RangeT> + inline detail::empty_formatF< + BOOST_STRING_TYPENAME range_value<RangeT>::type> + empty_formatter(const RangeT&) + { + return detail::empty_formatF< + BOOST_STRING_TYPENAME range_value<RangeT>::type>(); + } + + //! Empty formatter + /*! + Constructs a \c dissect_formatter. Dissect formatter uses a specified finder + 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 formatted sequence + \return An instance of the \c dissect_formatter object. + */ + template<typename FinderT> + inline detail::dissect_formatF< FinderT > + dissect_formatter(const FinderT& Finder) + { + return detail::dissect_formatF<FinderT>(Finder); + } + + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::const_formatter; + using algorithm::identity_formatter; + using algorithm::empty_formatter; + using algorithm::dissect_formatter; + +} // namespace boost + + +#endif // BOOST_FORMATTER_HPP
diff --git a/boost/boost/algorithm/string/iter_find.hpp b/boost/boost/algorithm/string/iter_find.hpp new file mode 100644 index 0000000..10424ab --- /dev/null +++ b/boost/boost/algorithm/string/iter_find.hpp
@@ -0,0 +1,193 @@ +// Boost string_algo library iter_find.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_ITER_FIND_HPP +#define BOOST_STRING_ITER_FIND_HPP + +#include <boost/algorithm/string/config.hpp> +#include <algorithm> +#include <iterator> +#include <boost/iterator/transform_iterator.hpp> + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/value_type.hpp> +#include <boost/range/as_literal.hpp> + +#include <boost/algorithm/string/concept.hpp> +#include <boost/algorithm/string/find_iterator.hpp> +#include <boost/algorithm/string/detail/util.hpp> + +/*! \file + Defines generic split algorithms. Split algorithms can be + used to divide a sequence into several part according + to a given criteria. Result is given as a 'container + of containers' where elements are copies or references + to extracted parts. + + There are two algorithms provided. One iterates over matching + substrings, the other one over the gaps between these matches. +*/ + +namespace boost { + namespace algorithm { + +// iterate find ---------------------------------------------------// + + //! Iter find algorithm + /*! + This algorithm executes a given finder in iteration on the input, + until the end of input is reached, or no match is found. + Iteration is done using built-in find_iterator, so the real + searching is performed only when needed. + In each iteration new match is found and added to the result. + + \param Result A 'container container' to contain the result of search. + Both outer and inner container must have constructor taking a pair + of iterators as an argument. + Typical type of the result is + \c std::vector<boost::iterator_range<iterator>> + (each element of such a vector will container a range delimiting + a match). + \param Input A container which will be searched. + \param Finder A Finder object used for searching + \return A reference to the result + + \note Prior content of the result will be overwritten. + */ + template< + typename SequenceSequenceT, + typename RangeT, + typename FinderT > + inline SequenceSequenceT& + iter_find( + SequenceSequenceT& Result, + RangeT& Input, + FinderT Finder ) + { + BOOST_CONCEPT_ASSERT(( + FinderConcept< + FinderT, + BOOST_STRING_TYPENAME range_iterator<RangeT>::type> + )); + + iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input)); + + typedef BOOST_STRING_TYPENAME + range_iterator<RangeT>::type input_iterator_type; + typedef find_iterator<input_iterator_type> find_iterator_type; + typedef detail::copy_iterator_rangeF< + BOOST_STRING_TYPENAME + range_value<SequenceSequenceT>::type, + input_iterator_type> copy_range_type; + + input_iterator_type InputEnd=::boost::end(lit_input); + + typedef transform_iterator<copy_range_type, find_iterator_type> + transform_iter_type; + + transform_iter_type itBegin= + ::boost::make_transform_iterator( + find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ), + copy_range_type()); + + transform_iter_type itEnd= + ::boost::make_transform_iterator( + find_iterator_type(), + copy_range_type()); + + SequenceSequenceT Tmp(itBegin, itEnd); + + Result.swap(Tmp); + return Result; + } + +// iterate split ---------------------------------------------------// + + //! Split find algorithm + /*! + This algorithm executes a given finder in iteration on the input, + until the end of input is reached, or no match is found. + Iteration is done using built-in find_iterator, so the real + searching is performed only when needed. + Each match is used as a separator of segments. These segments are then + returned in the result. + + \param Result A 'container container' to contain the result of search. + Both outer and inner container must have constructor taking a pair + of iterators as an argument. + Typical type of the result is + \c std::vector<boost::iterator_range<iterator>> + (each element of such a vector will container a range delimiting + a match). + \param Input A container which will be searched. + \param Finder A finder object used for searching + \return A reference to the result + + \note Prior content of the result will be overwritten. + */ + template< + typename SequenceSequenceT, + typename RangeT, + typename FinderT > + inline SequenceSequenceT& + iter_split( + SequenceSequenceT& Result, + RangeT& Input, + FinderT Finder ) + { + BOOST_CONCEPT_ASSERT(( + FinderConcept<FinderT, + BOOST_STRING_TYPENAME range_iterator<RangeT>::type> + )); + + iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input)); + + typedef BOOST_STRING_TYPENAME + range_iterator<RangeT>::type input_iterator_type; + typedef split_iterator<input_iterator_type> find_iterator_type; + typedef detail::copy_iterator_rangeF< + BOOST_STRING_TYPENAME + range_value<SequenceSequenceT>::type, + input_iterator_type> copy_range_type; + + input_iterator_type InputEnd=::boost::end(lit_input); + + typedef transform_iterator<copy_range_type, find_iterator_type> + transform_iter_type; + + transform_iter_type itBegin= + ::boost::make_transform_iterator( + find_iterator_type( ::boost::begin(lit_input), InputEnd, Finder ), + copy_range_type() ); + + transform_iter_type itEnd= + ::boost::make_transform_iterator( + find_iterator_type(), + copy_range_type() ); + + SequenceSequenceT Tmp(itBegin, itEnd); + + Result.swap(Tmp); + return Result; + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::iter_find; + using algorithm::iter_split; + +} // namespace boost + + +#endif // BOOST_STRING_ITER_FIND_HPP
diff --git a/boost/boost/algorithm/string/join.hpp b/boost/boost/algorithm/string/join.hpp new file mode 100644 index 0000000..b871eb4 --- /dev/null +++ b/boost/boost/algorithm/string/join.hpp
@@ -0,0 +1,145 @@ +// Boost string_algo library join.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_JOIN_HPP +#define BOOST_STRING_JOIN_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/algorithm/string/detail/sequence.hpp> +#include <boost/range/value_type.hpp> +#include <boost/range/as_literal.hpp> + +/*! \file + Defines join algorithm. + + Join algorithm is a counterpart to split algorithms. + It joins strings from a 'list' by adding user defined separator. + Additionally there is a version that allows simple filtering + by providing a predicate. +*/ + +namespace boost { + namespace algorithm { + +// join --------------------------------------------------------------// + + //! Join algorithm + /*! + This algorithm joins all strings in a 'list' into one long string. + Segments are concatenated by given separator. + + \param Input A container that holds the input strings. It must be a container-of-containers. + \param Separator A string that will separate the joined segments. + \return Concatenated string. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename Range1T> + inline typename range_value<SequenceSequenceT>::type + join( + const SequenceSequenceT& Input, + const Range1T& Separator) + { + // Define working types + typedef typename range_value<SequenceSequenceT>::type ResultT; + typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT; + + // Parse input + InputIteratorT itBegin=::boost::begin(Input); + InputIteratorT itEnd=::boost::end(Input); + + // Construct container to hold the result + ResultT Result; + + // Append first element + if(itBegin!=itEnd) + { + detail::insert(Result, ::boost::end(Result), *itBegin); + ++itBegin; + } + + for(;itBegin!=itEnd; ++itBegin) + { + // Add separator + detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator)); + // Add element + detail::insert(Result, ::boost::end(Result), *itBegin); + } + + return Result; + } + +// join_if ----------------------------------------------------------// + + //! Conditional join algorithm + /*! + This algorithm joins all strings in a 'list' into one long string. + Segments are concatenated by given separator. Only segments that + satisfy the predicate will be added to the result. + + \param Input A container that holds the input strings. It must be a container-of-containers. + \param Separator A string that will separate the joined segments. + \param Pred A segment selection predicate + \return Concatenated string. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename Range1T, typename PredicateT> + inline typename range_value<SequenceSequenceT>::type + join_if( + const SequenceSequenceT& Input, + const Range1T& Separator, + PredicateT Pred) + { + // Define working types + typedef typename range_value<SequenceSequenceT>::type ResultT; + typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT; + + // Parse input + InputIteratorT itBegin=::boost::begin(Input); + InputIteratorT itEnd=::boost::end(Input); + + // Construct container to hold the result + ResultT Result; + + // Roll to the first element that will be added + while(itBegin!=itEnd && !Pred(*itBegin)) ++itBegin; + // Add this element + if(itBegin!=itEnd) + { + detail::insert(Result, ::boost::end(Result), *itBegin); + ++itBegin; + } + + for(;itBegin!=itEnd; ++itBegin) + { + if(Pred(*itBegin)) + { + // Add separator + detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator)); + // Add element + detail::insert(Result, ::boost::end(Result), *itBegin); + } + } + + return Result; + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::join; + using algorithm::join_if; + +} // namespace boost + + +#endif // BOOST_STRING_JOIN_HPP +
diff --git a/boost/boost/algorithm/string/predicate.hpp b/boost/boost/algorithm/string/predicate.hpp new file mode 100644 index 0000000..0879829 --- /dev/null +++ b/boost/boost/algorithm/string/predicate.hpp
@@ -0,0 +1,475 @@ +// Boost string_algo library predicate.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_PREDICATE_HPP +#define BOOST_STRING_PREDICATE_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/const_iterator.hpp> +#include <boost/range/as_literal.hpp> +#include <boost/range/iterator_range_core.hpp> + +#include <boost/algorithm/string/compare.hpp> +#include <boost/algorithm/string/find.hpp> +#include <boost/algorithm/string/detail/predicate.hpp> + +/*! \file boost/algorithm/string/predicate.hpp + Defines string-related predicates. + The predicates determine whether a substring is contained in the input string + under various conditions: a string starts with the substring, ends with the + substring, simply contains the substring or if both strings are equal. + Additionaly the algorithm \c all() checks all elements of a container to satisfy a + condition. + + All predicates provide the strong exception guarantee. +*/ + +namespace boost { + namespace algorithm { + +// starts_with predicate -----------------------------------------------// + + //! 'Starts with' predicate + /*! + This predicate holds when the test string is a prefix of the Input. + In other words, if the input starts with the test. + When the optional predicate is specified, it is used for character-wise + comparison. + + \param Input An input sequence + \param Test A test sequence + \param Comp An element comparison predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T, typename PredicateT> + inline bool starts_with( + const Range1T& Input, + const Range2T& Test, + PredicateT Comp) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input)); + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test)); + + typedef BOOST_STRING_TYPENAME + range_const_iterator<Range1T>::type Iterator1T; + typedef BOOST_STRING_TYPENAME + range_const_iterator<Range2T>::type Iterator2T; + + Iterator1T InputEnd=::boost::end(lit_input); + Iterator2T TestEnd=::boost::end(lit_test); + + Iterator1T it=::boost::begin(lit_input); + Iterator2T pit=::boost::begin(lit_test); + for(; + it!=InputEnd && pit!=TestEnd; + ++it,++pit) + { + if( !(Comp(*it,*pit)) ) + return false; + } + + return pit==TestEnd; + } + + //! 'Starts with' predicate + /*! + \overload + */ + template<typename Range1T, typename Range2T> + inline bool starts_with( + const Range1T& Input, + const Range2T& Test) + { + return ::boost::algorithm::starts_with(Input, Test, is_equal()); + } + + //! 'Starts with' predicate ( case insensitive ) + /*! + This predicate holds when the test string is a prefix of the Input. + In other words, if the input starts with the test. + Elements are compared case insensitively. + + \param Input An input sequence + \param Test A test sequence + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline bool istarts_with( + const Range1T& Input, + const Range2T& Test, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::starts_with(Input, Test, is_iequal(Loc)); + } + + +// ends_with predicate -----------------------------------------------// + + //! 'Ends with' predicate + /*! + This predicate holds when the test string is a suffix of the Input. + In other words, if the input ends with the test. + When the optional predicate is specified, it is used for character-wise + comparison. + + + \param Input An input sequence + \param Test A test sequence + \param Comp An element comparison predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T, typename PredicateT> + inline bool ends_with( + const Range1T& Input, + const Range2T& Test, + PredicateT Comp) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input)); + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test)); + + typedef BOOST_STRING_TYPENAME + range_const_iterator<Range1T>::type Iterator1T; + typedef BOOST_STRING_TYPENAME boost::detail:: + iterator_traits<Iterator1T>::iterator_category category; + + return detail:: + ends_with_iter_select( + ::boost::begin(lit_input), + ::boost::end(lit_input), + ::boost::begin(lit_test), + ::boost::end(lit_test), + Comp, + category()); + } + + + //! 'Ends with' predicate + /*! + \overload + */ + template<typename Range1T, typename Range2T> + inline bool ends_with( + const Range1T& Input, + const Range2T& Test) + { + return ::boost::algorithm::ends_with(Input, Test, is_equal()); + } + + //! 'Ends with' predicate ( case insensitive ) + /*! + This predicate holds when the test container is a suffix of the Input. + In other words, if the input ends with the test. + Elements are compared case insensitively. + + \param Input An input sequence + \param Test A test sequence + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline bool iends_with( + const Range1T& Input, + const Range2T& Test, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::ends_with(Input, Test, is_iequal(Loc)); + } + +// contains predicate -----------------------------------------------// + + //! 'Contains' predicate + /*! + This predicate holds when the test container is contained in the Input. + When the optional predicate is specified, it is used for character-wise + comparison. + + \param Input An input sequence + \param Test A test sequence + \param Comp An element comparison predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T, typename PredicateT> + inline bool contains( + const Range1T& Input, + const Range2T& Test, + PredicateT Comp) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input)); + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test)); + + if (::boost::empty(lit_test)) + { + // Empty range is contained always + return true; + } + + // Use the temporary variable to make VACPP happy + bool bResult=(::boost::algorithm::first_finder(lit_test,Comp)(::boost::begin(lit_input), ::boost::end(lit_input))); + return bResult; + } + + //! 'Contains' predicate + /*! + \overload + */ + template<typename Range1T, typename Range2T> + inline bool contains( + const Range1T& Input, + const Range2T& Test) + { + return ::boost::algorithm::contains(Input, Test, is_equal()); + } + + //! 'Contains' predicate ( case insensitive ) + /*! + This predicate holds when the test container is contained in the Input. + Elements are compared case insensitively. + + \param Input An input sequence + \param Test A test sequence + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline bool icontains( + const Range1T& Input, + const Range2T& Test, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::contains(Input, Test, is_iequal(Loc)); + } + +// equals predicate -----------------------------------------------// + + //! 'Equals' predicate + /*! + This predicate holds when the test container is equal to the + input container i.e. all elements in both containers are same. + When the optional predicate is specified, it is used for character-wise + comparison. + + \param Input An input sequence + \param Test A test sequence + \param Comp An element comparison predicate + \return The result of the test + + \note This is a two-way version of \c std::equal algorithm + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T, typename PredicateT> + inline bool equals( + const Range1T& Input, + const Range2T& Test, + PredicateT Comp) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_input(::boost::as_literal(Input)); + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_test(::boost::as_literal(Test)); + + typedef BOOST_STRING_TYPENAME + range_const_iterator<Range1T>::type Iterator1T; + typedef BOOST_STRING_TYPENAME + range_const_iterator<Range2T>::type Iterator2T; + + Iterator1T InputEnd=::boost::end(lit_input); + Iterator2T TestEnd=::boost::end(lit_test); + + Iterator1T it=::boost::begin(lit_input); + Iterator2T pit=::boost::begin(lit_test); + for(; + it!=InputEnd && pit!=TestEnd; + ++it,++pit) + { + if( !(Comp(*it,*pit)) ) + return false; + } + + return (pit==TestEnd) && (it==InputEnd); + } + + //! 'Equals' predicate + /*! + \overload + */ + template<typename Range1T, typename Range2T> + inline bool equals( + const Range1T& Input, + const Range2T& Test) + { + return ::boost::algorithm::equals(Input, Test, is_equal()); + } + + //! 'Equals' predicate ( case insensitive ) + /*! + This predicate holds when the test container is equal to the + input container i.e. all elements in both containers are same. + Elements are compared case insensitively. + + \param Input An input sequence + \param Test A test sequence + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This is a two-way version of \c std::equal algorithm + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline bool iequals( + const Range1T& Input, + const Range2T& Test, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::equals(Input, Test, is_iequal(Loc)); + } + +// lexicographical_compare predicate -----------------------------// + + //! Lexicographical compare predicate + /*! + This predicate is an overload of std::lexicographical_compare + for range arguments + + It check whether the first argument is lexicographically less + then the second one. + + If the optional predicate is specified, it is used for character-wise + comparison + + \param Arg1 First argument + \param Arg2 Second argument + \param Pred Comparison predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T, typename PredicateT> + inline bool lexicographical_compare( + const Range1T& Arg1, + const Range2T& Arg2, + PredicateT Pred) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range1T>::type> lit_arg1(::boost::as_literal(Arg1)); + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<Range2T>::type> lit_arg2(::boost::as_literal(Arg2)); + + return std::lexicographical_compare( + ::boost::begin(lit_arg1), + ::boost::end(lit_arg1), + ::boost::begin(lit_arg2), + ::boost::end(lit_arg2), + Pred); + } + + //! Lexicographical compare predicate + /*! + \overload + */ + template<typename Range1T, typename Range2T> + inline bool lexicographical_compare( + const Range1T& Arg1, + const Range2T& Arg2) + { + return ::boost::algorithm::lexicographical_compare(Arg1, Arg2, is_less()); + } + + //! Lexicographical compare predicate (case-insensitive) + /*! + This predicate is an overload of std::lexicographical_compare + for range arguments. + It check whether the first argument is lexicographically less + then the second one. + Elements are compared case insensitively + + + \param Arg1 First argument + \param Arg2 Second argument + \param Loc A locale used for case insensitive comparison + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template<typename Range1T, typename Range2T> + inline bool ilexicographical_compare( + const Range1T& Arg1, + const Range2T& Arg2, + const std::locale& Loc=std::locale()) + { + return ::boost::algorithm::lexicographical_compare(Arg1, Arg2, is_iless(Loc)); + } + + +// all predicate -----------------------------------------------// + + //! 'All' predicate + /*! + This predicate holds it all its elements satisfy a given + condition, represented by the predicate. + + \param Input An input sequence + \param Pred A predicate + \return The result of the test + + \note This function provides the strong exception-safety guarantee + */ + template<typename RangeT, typename PredicateT> + inline bool all( + const RangeT& Input, + PredicateT Pred) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_input(::boost::as_literal(Input)); + + typedef BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type Iterator1T; + + Iterator1T InputEnd=::boost::end(lit_input); + for( Iterator1T It=::boost::begin(lit_input); It!=InputEnd; ++It) + { + if (!Pred(*It)) + return false; + } + + return true; + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::starts_with; + using algorithm::istarts_with; + using algorithm::ends_with; + using algorithm::iends_with; + using algorithm::contains; + using algorithm::icontains; + using algorithm::equals; + using algorithm::iequals; + using algorithm::all; + using algorithm::lexicographical_compare; + using algorithm::ilexicographical_compare; + +} // namespace boost + + +#endif // BOOST_STRING_PREDICATE_HPP
diff --git a/boost/boost/algorithm/string/predicate_facade.hpp b/boost/boost/algorithm/string/predicate_facade.hpp new file mode 100644 index 0000000..a9753fc --- /dev/null +++ b/boost/boost/algorithm/string/predicate_facade.hpp
@@ -0,0 +1,42 @@ +// Boost string_algo library predicate_facade.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_PREDICATE_FACADE_HPP +#define BOOST_STRING_PREDICATE_FACADE_HPP + +#include <boost/algorithm/string/config.hpp> + +/* + \file boost/algorith/string/predicate_facade.hpp + This file contains predicate_facade definition. This template class is used + to identify classification predicates, so they can be combined using + composition operators. +*/ + +namespace boost { + namespace algorithm { + +// predicate facade ------------------------------------------------------// + + //! Predicate facade + /*! + This class allows to recognize classification + predicates, so that they can be combined using + composition operators. + Every classification predicate must be derived from this class. + */ + template<typename Derived> + struct predicate_facade {}; + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_CLASSIFICATION_DETAIL_HPP
diff --git a/boost/boost/algorithm/string/regex.hpp b/boost/boost/algorithm/string/regex.hpp new file mode 100644 index 0000000..a6c7c60 --- /dev/null +++ b/boost/boost/algorithm/string/regex.hpp
@@ -0,0 +1,646 @@ +// Boost string_algo library regex.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_REGEX_HPP +#define BOOST_STRING_REGEX_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/regex.hpp> + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/as_literal.hpp> + +#include <boost/algorithm/string/find_format.hpp> +#include <boost/algorithm/string/regex_find_format.hpp> +#include <boost/algorithm/string/formatter.hpp> +#include <boost/algorithm/string/iter_find.hpp> + +/*! \file + Defines regex variants of the algorithms. +*/ + +namespace boost { + namespace algorithm { + +// find_regex -----------------------------------------------// + + //! Find regex algorithm + /*! + Search for a substring matching the given regex in the input. + + \param Input A container which will be searched. + \param Rx A regular expression + \param Flags Regex options + \return + An \c iterator_range delimiting the match. + Returned iterator is either \c RangeT::iterator or + \c RangeT::const_iterator, depending on the constness of + the input parameter. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename RangeT, + typename CharT, + typename RegexTraitsT> + inline iterator_range< + BOOST_STRING_TYPENAME range_iterator<RangeT>::type > + find_regex( + RangeT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + iterator_range<BOOST_STRING_TYPENAME range_iterator<RangeT>::type> lit_input(::boost::as_literal(Input)); + + return ::boost::algorithm::regex_finder(Rx,Flags)( + ::boost::begin(lit_input), ::boost::end(lit_input) ); + } + +// replace_regex --------------------------------------------------------------------// + + //! Replace regex algorithm + /*! + Search for a substring matching given regex and format it with + the specified format. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Rx A regular expression + \param Format Regex format definition + \param Flags Regex options + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline OutputIteratorT replace_regex_copy( + OutputIteratorT Output, + const RangeT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format, + match_flag_type Flags=match_default | format_default ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::regex_formatter( Format, Flags ) ); + } + + //! Replace regex algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline SequenceT replace_regex_copy( + const SequenceT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format, + match_flag_type Flags=match_default | format_default ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::regex_formatter( Format, Flags ) ); + } + + //! Replace regex algorithm + /*! + Search for a substring matching given regex and format it with + the specified format. The input string is modified in-place. + + \param Input An input string + \param Rx A regular expression + \param Format Regex format definition + \param Flags Regex options + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline void replace_regex( + SequenceT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format, + match_flag_type Flags=match_default | format_default ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::regex_formatter( Format, Flags ) ); + } + +// replace_all_regex --------------------------------------------------------------------// + + //! Replace all regex algorithm + /*! + Format all substrings, matching given regex, with the specified format. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Rx A regular expression + \param Format Regex format definition + \param Flags Regex options + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline OutputIteratorT replace_all_regex_copy( + OutputIteratorT Output, + const RangeT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format, + match_flag_type Flags=match_default | format_default ) + { + return ::boost::algorithm::find_format_all_copy( + Output, + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::regex_formatter( Format, Flags ) ); + } + + //! Replace all regex algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline SequenceT replace_all_regex_copy( + const SequenceT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format, + match_flag_type Flags=match_default | format_default ) + { + return ::boost::algorithm::find_format_all_copy( + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::regex_formatter( Format, Flags ) ); + } + + //! Replace all regex algorithm + /*! + Format all substrings, matching given regex, with the specified format. + The input string is modified in-place. + + \param Input An input string + \param Rx A regular expression + \param Format Regex format definition + \param Flags Regex options + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT, + typename FormatStringTraitsT, typename FormatStringAllocatorT > + inline void replace_all_regex( + SequenceT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + const std::basic_string<CharT, FormatStringTraitsT, FormatStringAllocatorT>& Format, + match_flag_type Flags=match_default | format_default ) + { + ::boost::algorithm::find_format_all( + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::regex_formatter( Format, Flags ) ); + } + +// erase_regex --------------------------------------------------------------------// + + //! Erase regex algorithm + /*! + Remove a substring matching given regex from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Rx A regular expression + \param Flags Regex options + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename CharT, + typename RegexTraitsT > + inline OutputIteratorT erase_regex_copy( + OutputIteratorT Output, + const RangeT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::empty_formatter( Input ) ); + } + + //! Erase regex algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT > + inline SequenceT erase_regex_copy( + const SequenceT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::empty_formatter( Input ) ); + } + + //! Erase regex algorithm + /*! + Remove a substring matching given regex from the input. + The input string is modified in-place. + + \param Input An input string + \param Rx A regular expression + \param Flags Regex options + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT > + inline void erase_regex( + SequenceT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::empty_formatter( Input ) ); + } + +// erase_all_regex --------------------------------------------------------------------// + + //! Erase all regex algorithm + /*! + Erase all substrings, matching given regex, from the input. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Rx A regular expression + \param Flags Regex options + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename RangeT, + typename CharT, + typename RegexTraitsT > + inline OutputIteratorT erase_all_regex_copy( + OutputIteratorT Output, + const RangeT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + return ::boost::algorithm::find_format_all_copy( + Output, + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::empty_formatter( Input ) ); + } + + //! Erase all regex algorithm + /*! + \overload + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT > + inline SequenceT erase_all_regex_copy( + const SequenceT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + return ::boost::algorithm::find_format_all_copy( + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::empty_formatter( Input ) ); + } + + //! Erase all regex algorithm + /*! + Erase all substrings, matching given regex, from the input. + The input string is modified in-place. + + \param Input An input string + \param Rx A regular expression + \param Flags Regex options + */ + template< + typename SequenceT, + typename CharT, + typename RegexTraitsT> + inline void erase_all_regex( + SequenceT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + ::boost::algorithm::find_format_all( + Input, + ::boost::algorithm::regex_finder( Rx, Flags ), + ::boost::algorithm::empty_formatter( Input ) ); + } + +// find_all_regex ------------------------------------------------------------------// + + //! Find all regex algorithm + /*! + This algorithm finds all substrings matching the give regex + in the input. + + Each part is copied and added as a new element to the output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector<std::string> + or \c std::list<boost::iterator_range<std::string::iterator>> + + \param Result A container that can hold copies of references to the substrings. + \param Input A container which will be searched. + \param Rx A regular expression + \param Flags Regex options + \return A reference to the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename SequenceSequenceT, + typename RangeT, + typename CharT, + typename RegexTraitsT > + inline SequenceSequenceT& find_all_regex( + SequenceSequenceT& Result, + const RangeT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + return ::boost::algorithm::iter_find( + Result, + Input, + ::boost::algorithm::regex_finder(Rx,Flags) ); + } + +// split_regex ------------------------------------------------------------------// + + //! Split regex algorithm + /*! + Tokenize expression. This function is equivalent to C strtok. Input + sequence is split into tokens, separated by separators. Separator + is an every match of the given regex. + Each part is copied and added as a new element to the output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector<std::string> + or \c std::list<boost::iterator_range<std::string::iterator>> + + \param Result A container that can hold copies of references to the substrings. + \param Input A container which will be searched. + \param Rx A regular expression + \param Flags Regex options + \return A reference to the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename SequenceSequenceT, + typename RangeT, + typename CharT, + typename RegexTraitsT > + inline SequenceSequenceT& split_regex( + SequenceSequenceT& Result, + const RangeT& Input, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + return ::boost::algorithm::iter_split( + Result, + Input, + ::boost::algorithm::regex_finder(Rx,Flags) ); + } + +// join_if ------------------------------------------------------------------// + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + //! Conditional join algorithm + /*! + This algorithm joins all strings in a 'list' into one long string. + Segments are concatenated by given separator. Only segments that + match the given regular expression will be added to the result + + This is a specialization of join_if algorithm. + + \param Input A container that holds the input strings. It must be a container-of-containers. + \param Separator A string that will separate the joined segments. + \param Rx A regular expression + \param Flags Regex options + \return Concatenated string. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename SequenceSequenceT, + typename Range1T, + typename CharT, + typename RegexTraitsT > + inline typename range_value<SequenceSequenceT>::type + join_if( + const SequenceSequenceT& Input, + const Range1T& Separator, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + // Define working types + typedef typename range_value<SequenceSequenceT>::type ResultT; + typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT; + + // Parse input + InputIteratorT itBegin=::boost::begin(Input); + InputIteratorT itEnd=::boost::end(Input); + + // Construct container to hold the result + ResultT Result; + + + // Roll to the first element that will be added + while( + itBegin!=itEnd && + !::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) ++itBegin; + + // Add this element + if(itBegin!=itEnd) + { + detail::insert(Result, ::boost::end(Result), *itBegin); + ++itBegin; + } + + for(;itBegin!=itEnd; ++itBegin) + { + if(::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) + { + // Add separator + detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator)); + // Add element + detail::insert(Result, ::boost::end(Result), *itBegin); + } + } + + return Result; + } + +#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + //! Conditional join algorithm + /*! + This algorithm joins all strings in a 'list' into one long string. + Segments are concatenated by given separator. Only segments that + match the given regular expression will be added to the result + + This is a specialization of join_if algorithm. + + \param Input A container that holds the input strings. It must be a container-of-containers. + \param Separator A string that will separate the joined segments. + \param Rx A regular expression + \param Flags Regex options + \return Concatenated string. + + \note This function provides the strong exception-safety guarantee + */ + template< + typename SequenceSequenceT, + typename Range1T, + typename CharT, + typename RegexTraitsT > + inline typename range_value<SequenceSequenceT>::type + join_if_regex( + const SequenceSequenceT& Input, + const Range1T& Separator, + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type Flags=match_default ) + { + // Define working types + typedef typename range_value<SequenceSequenceT>::type ResultT; + typedef typename range_const_iterator<SequenceSequenceT>::type InputIteratorT; + + // Parse input + InputIteratorT itBegin=::boost::begin(Input); + InputIteratorT itEnd=::boost::end(Input); + + // Construct container to hold the result + ResultT Result; + + + // Roll to the first element that will be added + while( + itBegin!=itEnd && + !::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) ++itBegin; + + // Add this element + if(itBegin!=itEnd) + { + detail::insert(Result, ::boost::end(Result), *itBegin); + ++itBegin; + } + + for(;itBegin!=itEnd; ++itBegin) + { + if(::boost::regex_match(::boost::begin(*itBegin), ::boost::end(*itBegin), Rx, Flags)) + { + // Add separator + detail::insert(Result, ::boost::end(Result), ::boost::as_literal(Separator)); + // Add element + detail::insert(Result, ::boost::end(Result), *itBegin); + } + } + + return Result; + } + + +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + + } // namespace algorithm + + // pull names into the boost namespace + using algorithm::find_regex; + using algorithm::replace_regex; + using algorithm::replace_regex_copy; + using algorithm::replace_all_regex; + using algorithm::replace_all_regex_copy; + using algorithm::erase_regex; + using algorithm::erase_regex_copy; + using algorithm::erase_all_regex; + using algorithm::erase_all_regex_copy; + using algorithm::find_all_regex; + using algorithm::split_regex; + +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + using algorithm::join_if; +#else // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + using algorithm::join_if_regex; +#endif // BOOST_NO_FUNCTION_TEMPLATE_ORDERING + +} // namespace boost + + +#endif // BOOST_STRING_REGEX_HPP
diff --git a/boost/boost/algorithm/string/regex_find_format.hpp b/boost/boost/algorithm/string/regex_find_format.hpp new file mode 100644 index 0000000..409afc2 --- /dev/null +++ b/boost/boost/algorithm/string/regex_find_format.hpp
@@ -0,0 +1,90 @@ +// Boost string_algo library regex_find_format.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_REGEX_FIND_FORMAT_HPP +#define BOOST_STRING_REGEX_FIND_FORMAT_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/regex.hpp> +#include <boost/algorithm/string/detail/finder_regex.hpp> +#include <boost/algorithm/string/detail/formatter_regex.hpp> + +/*! \file + Defines the \c regex_finder and \c regex_formatter generators. These two functors + are designed to work together. \c regex_formatter uses additional information + about a match contained in the regex_finder search result. +*/ + +namespace boost { + namespace algorithm { + +// regex_finder -----------------------------------------------// + + //! "Regex" finder + /*! + Construct the \c regex_finder. Finder uses the regex engine to search + for a match. + Result is given in \c regex_search_result. This is an extension + of the iterator_range. In addition it contains match results + from the \c regex_search algorithm. + + \param Rx A regular expression + \param MatchFlags Regex search options + \return An instance of the \c regex_finder object + */ + template< + typename CharT, + typename RegexTraitsT> + inline detail::find_regexF< basic_regex<CharT, RegexTraitsT> > + regex_finder( + const basic_regex<CharT, RegexTraitsT>& Rx, + match_flag_type MatchFlags=match_default ) + { + return detail:: + find_regexF< + basic_regex<CharT, RegexTraitsT> >( Rx, MatchFlags ); + } + +// regex_formater ---------------------------------------------// + + //! Regex formatter + /*! + Construct the \c regex_formatter. Regex formatter uses the regex engine to + format a match found by the \c regex_finder. + This formatted it designed to closely cooperate with \c regex_finder. + + \param Format Regex format definition + \param Flags Format flags + \return An instance of the \c regex_formatter functor + */ + template< + typename CharT, + typename TraitsT, typename AllocT > + inline detail::regex_formatF< std::basic_string< CharT, TraitsT, AllocT > > + regex_formatter( + const std::basic_string<CharT, TraitsT, AllocT>& Format, + match_flag_type Flags=format_default ) + { + return + detail::regex_formatF< std::basic_string<CharT, TraitsT, AllocT> >( + Format, + Flags ); + } + + } // namespace algorithm + + // pull the names to the boost namespace + using algorithm::regex_finder; + using algorithm::regex_formatter; + +} // namespace boost + + +#endif // BOOST_STRING_REGEX_FIND_FORMAT_HPP
diff --git a/boost/boost/algorithm/string/replace.hpp b/boost/boost/algorithm/string/replace.hpp new file mode 100644 index 0000000..0c04e47 --- /dev/null +++ b/boost/boost/algorithm/string/replace.hpp
@@ -0,0 +1,928 @@ +// Boost string_algo library replace.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_REPLACE_HPP +#define BOOST_STRING_REPLACE_HPP + +#include <boost/algorithm/string/config.hpp> + +#include <boost/range/iterator_range_core.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/range/const_iterator.hpp> + +#include <boost/algorithm/string/find_format.hpp> +#include <boost/algorithm/string/finder.hpp> +#include <boost/algorithm/string/formatter.hpp> +#include <boost/algorithm/string/compare.hpp> + +/*! \file + Defines various replace algorithms. Each algorithm replaces + part(s) of the input according to set of searching and replace criteria. +*/ + +namespace boost { + namespace algorithm { + +// replace_range --------------------------------------------------------------------// + + //! Replace range algorithm + /*! + Replace the given range in the input string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param SearchRange A range in the input to be substituted + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT replace_range_copy( + OutputIteratorT Output, + const Range1T& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_const_iterator<Range1T>::type>& SearchRange, + const Range2T& Format) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::range_finder(SearchRange), + ::boost::algorithm::const_formatter(Format)); + } + + //! Replace range algorithm + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT replace_range_copy( + const SequenceT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_const_iterator<SequenceT>::type>& SearchRange, + const RangeT& Format) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::range_finder(SearchRange), + ::boost::algorithm::const_formatter(Format)); + } + + //! Replace range algorithm + /*! + Replace the given range in the input string. + The input sequence is modified in-place. + + \param Input An input string + \param SearchRange A range in the input to be substituted + \param Format A substitute string + */ + template<typename SequenceT, typename RangeT> + inline void replace_range( + SequenceT& Input, + const iterator_range< + BOOST_STRING_TYPENAME + range_iterator<SequenceT>::type>& SearchRange, + const RangeT& Format) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::range_finder(SearchRange), + ::boost::algorithm::const_formatter(Format)); + } + +// replace_first --------------------------------------------------------------------// + + //! Replace first algorithm + /*! + Replace the first match of the search substring in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT replace_first_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace first algorithm + /*! + \overload + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline SequenceT replace_first_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace first algorithm + /*! + replace the first match of the search substring in the input + with the format string. The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline void replace_first( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::const_formatter(Format) ); + } + +// replace_first ( case insensitive ) ---------------------------------------------// + + //! Replace first algorithm ( case insensitive ) + /*! + Replace the first match of the search substring in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT ireplace_first_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace first algorithm ( case insensitive ) + /*! + \overload + */ + template<typename SequenceT, typename Range2T, typename Range1T> + inline SequenceT ireplace_first_copy( + const SequenceT& Input, + const Range2T& Search, + const Range1T& Format, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace first algorithm ( case insensitive ) + /*! + Replace the first match of the search substring in the input + with the format string. Input sequence is modified in-place. + Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline void ireplace_first( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + +// replace_last --------------------------------------------------------------------// + + //! Replace last algorithm + /*! + Replace the last match of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT replace_last_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::last_finder(Search), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace last algorithm + /*! + \overload + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline SequenceT replace_last_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::last_finder(Search), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace last algorithm + /*! + Replace the last match of the search string in the input + with the format string. Input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline void replace_last( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::last_finder(Search), + ::boost::algorithm::const_formatter(Format) ); + } + +// replace_last ( case insensitive ) -----------------------------------------------// + + //! Replace last algorithm ( case insensitive ) + /*! + Replace the last match of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT ireplace_last_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::last_finder(Search, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace last algorithm ( case insensitive ) + /*! + \overload + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline SequenceT ireplace_last_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::last_finder(Search, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace last algorithm ( case insensitive ) + /*! + Replace the last match of the search string in the input + with the format string.The input sequence is modified in-place. + Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return A reference to the modified input + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline void ireplace_last( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::last_finder(Search, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + +// replace_nth --------------------------------------------------------------------// + + //! Replace nth algorithm + /*! + Replace an Nth (zero-indexed) match of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT replace_nth_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + int Nth, + const Range3T& Format ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::nth_finder(Search, Nth), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace nth algorithm + /*! + \overload + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline SequenceT replace_nth_copy( + const SequenceT& Input, + const Range1T& Search, + int Nth, + const Range2T& Format ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::nth_finder(Search, Nth), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace nth algorithm + /*! + Replace an Nth (zero-indexed) match of the search string in the input + with the format string. Input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Format A substitute string + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline void replace_nth( + SequenceT& Input, + const Range1T& Search, + int Nth, + const Range2T& Format ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::nth_finder(Search, Nth), + ::boost::algorithm::const_formatter(Format) ); + } + +// replace_nth ( case insensitive ) -----------------------------------------------// + + //! Replace nth algorithm ( case insensitive ) + /*! + Replace an Nth (zero-indexed) match of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT ireplace_nth_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + int Nth, + const Range3T& Format, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc) ), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace nth algorithm ( case insensitive ) + /*! + \overload + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline SequenceT ireplace_nth_copy( + const SequenceT& Input, + const Range1T& Search, + int Nth, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace nth algorithm ( case insensitive ) + /*! + Replace an Nth (zero-indexed) match of the search string in the input + with the format string. Input sequence is modified in-place. + Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Nth An index of the match to be replaced. The index is 0-based. + For negative N, matches are counted from the end of string. + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline void ireplace_nth( + SequenceT& Input, + const Range1T& Search, + int Nth, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::nth_finder(Search, Nth, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + +// replace_all --------------------------------------------------------------------// + + //! Replace all algorithm + /*! + Replace all occurrences of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT replace_all_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format ) + { + return ::boost::algorithm::find_format_all_copy( + Output, + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace all algorithm + /*! + \overload + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline SequenceT replace_all_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + return ::boost::algorithm::find_format_all_copy( + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace all algorithm + /*! + Replace all occurrences of the search string in the input + with the format string. The input sequence is modified in-place. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \return A reference to the modified input + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline void replace_all( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format ) + { + ::boost::algorithm::find_format_all( + Input, + ::boost::algorithm::first_finder(Search), + ::boost::algorithm::const_formatter(Format) ); + } + +// replace_all ( case insensitive ) -----------------------------------------------// + + //! Replace all algorithm ( case insensitive ) + /*! + Replace all occurrences of the search string in the input + with the format string. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + Searching is case insensitive. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T, + typename Range3T> + inline OutputIteratorT ireplace_all_copy( + OutputIteratorT Output, + const Range1T& Input, + const Range2T& Search, + const Range3T& Format, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_all_copy( + Output, + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace all algorithm ( case insensitive ) + /*! + \overload + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline SequenceT ireplace_all_copy( + const SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::find_format_all_copy( + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace all algorithm ( case insensitive ) + /*! + Replace all occurrences of the search string in the input + with the format string.The input sequence is modified in-place. + Searching is case insensitive. + + \param Input An input string + \param Search A substring to be searched for + \param Format A substitute string + \param Loc A locale used for case insensitive comparison + */ + template<typename SequenceT, typename Range1T, typename Range2T> + inline void ireplace_all( + SequenceT& Input, + const Range1T& Search, + const Range2T& Format, + const std::locale& Loc=std::locale() ) + { + ::boost::algorithm::find_format_all( + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc)), + ::boost::algorithm::const_formatter(Format) ); + } + +// replace_head --------------------------------------------------------------------// + + //! Replace head algorithm + /*! + Replace the head of the input with the given format string. + The head is a prefix of a string of given size. + If the sequence is shorter then required, whole string if + considered to be the head. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param N Length of the head. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT replace_head_copy( + OutputIteratorT Output, + const Range1T& Input, + int N, + const Range2T& Format ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::head_finder(N), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace head algorithm + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT replace_head_copy( + const SequenceT& Input, + int N, + const RangeT& Format ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::head_finder(N), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace head algorithm + /*! + Replace the head of the input with the given format string. + The head is a prefix of a string of given size. + If the sequence is shorter then required, the whole string is + considered to be the head. The input sequence is modified in-place. + + \param Input An input string + \param N Length of the head. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \param Format A substitute string + */ + template<typename SequenceT, typename RangeT> + inline void replace_head( + SequenceT& Input, + int N, + const RangeT& Format ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::head_finder(N), + ::boost::algorithm::const_formatter(Format) ); + } + +// replace_tail --------------------------------------------------------------------// + + //! Replace tail algorithm + /*! + Replace the tail of the input with the given format string. + The tail is a suffix of a string of given size. + If the sequence is shorter then required, whole string is + considered to be the tail. + The result is a modified copy of the input. It is returned as a sequence + or copied to the output iterator. + + \param Output An output iterator to which the result will be copied + \param Input An input string + \param N Length of the tail. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \param Format A substitute string + \return An output iterator pointing just after the last inserted character or + a modified copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template< + typename OutputIteratorT, + typename Range1T, + typename Range2T> + inline OutputIteratorT replace_tail_copy( + OutputIteratorT Output, + const Range1T& Input, + int N, + const Range2T& Format ) + { + return ::boost::algorithm::find_format_copy( + Output, + Input, + ::boost::algorithm::tail_finder(N), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace tail algorithm + /*! + \overload + */ + template<typename SequenceT, typename RangeT> + inline SequenceT replace_tail_copy( + const SequenceT& Input, + int N, + const RangeT& Format ) + { + return ::boost::algorithm::find_format_copy( + Input, + ::boost::algorithm::tail_finder(N), + ::boost::algorithm::const_formatter(Format) ); + } + + //! Replace tail algorithm + /*! + Replace the tail of the input with the given format sequence. + The tail is a suffix of a string of given size. + If the sequence is shorter then required, the whole string is + considered to be the tail. The input sequence is modified in-place. + + \param Input An input string + \param N Length of the tail. + For N>=0, at most N characters are extracted. + For N<0, size(Input)-|N| characters are extracted. + \param Format A substitute string + */ + template<typename SequenceT, typename RangeT> + inline void replace_tail( + SequenceT& Input, + int N, + const RangeT& Format ) + { + ::boost::algorithm::find_format( + Input, + ::boost::algorithm::tail_finder(N), + ::boost::algorithm::const_formatter(Format) ); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::replace_range_copy; + using algorithm::replace_range; + using algorithm::replace_first_copy; + using algorithm::replace_first; + using algorithm::ireplace_first_copy; + using algorithm::ireplace_first; + using algorithm::replace_last_copy; + using algorithm::replace_last; + using algorithm::ireplace_last_copy; + using algorithm::ireplace_last; + using algorithm::replace_nth_copy; + using algorithm::replace_nth; + using algorithm::ireplace_nth_copy; + using algorithm::ireplace_nth; + using algorithm::replace_all_copy; + using algorithm::replace_all; + using algorithm::ireplace_all_copy; + using algorithm::ireplace_all; + using algorithm::replace_head_copy; + using algorithm::replace_head; + using algorithm::replace_tail_copy; + using algorithm::replace_tail; + +} // namespace boost + +#endif // BOOST_REPLACE_HPP
diff --git a/boost/boost/algorithm/string/sequence_traits.hpp b/boost/boost/algorithm/string/sequence_traits.hpp new file mode 100644 index 0000000..be151f8 --- /dev/null +++ b/boost/boost/algorithm/string/sequence_traits.hpp
@@ -0,0 +1,120 @@ +// Boost string_algo library sequence_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_SEQUENCE_TRAITS_HPP +#define BOOST_STRING_SEQUENCE_TRAITS_HPP + +#include <boost/config.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/algorithm/string/yes_no_type.hpp> + +/*! \file + Traits defined in this header are used by various algorithms to achieve + better performance for specific containers. + Traits provide fail-safe defaults. If a container supports some of these + features, it is possible to specialize the specific trait for this container. + For lacking compilers, it is possible of define an override for a specific tester + function. + + Due to a language restriction, it is not currently possible to define specializations for + stl containers without including the corresponding header. To decrease the overhead + needed by this inclusion, user can selectively include a specialization + header for a specific container. They are located in boost/algorithm/string/stl + directory. Alternatively she can include boost/algorithm/string/std_collection_traits.hpp + header which contains specializations for all stl containers. +*/ + +namespace boost { + namespace algorithm { + +// sequence traits -----------------------------------------------// + + + //! Native replace trait + /*! + This trait specifies that the sequence has \c std::string like replace method + */ + template< typename T > + class has_native_replace + { + + public: +# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = false }; +# else + BOOST_STATIC_CONSTANT(bool, value=false); +# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + + + typedef mpl::bool_<has_native_replace<T>::value> type; + }; + + + //! Stable iterators trait + /*! + This trait specifies that the sequence has stable iterators. It means + that operations like insert/erase/replace do not invalidate iterators. + */ + template< typename T > + class has_stable_iterators + { + public: +# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = false }; +# else + BOOST_STATIC_CONSTANT(bool, value=false); +# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + + typedef mpl::bool_<has_stable_iterators<T>::value> type; + }; + + + //! Const time insert trait + /*! + This trait specifies that the sequence's insert method has + constant time complexity. + */ + template< typename T > + class has_const_time_insert + { + public: +# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = false }; +# else + BOOST_STATIC_CONSTANT(bool, value=false); +# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + + typedef mpl::bool_<has_const_time_insert<T>::value> type; + }; + + + //! Const time erase trait + /*! + This trait specifies that the sequence's erase method has + constant time complexity. + */ + template< typename T > + class has_const_time_erase + { + public: +# if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = false }; +# else + BOOST_STATIC_CONSTANT(bool, value=false); +# endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + + typedef mpl::bool_<has_const_time_erase<T>::value> type; + }; + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_SEQUENCE_TRAITS_HPP
diff --git a/boost/boost/algorithm/string/split.hpp b/boost/boost/algorithm/string/split.hpp new file mode 100644 index 0000000..cae712c --- /dev/null +++ b/boost/boost/algorithm/string/split.hpp
@@ -0,0 +1,163 @@ +// Boost string_algo library split.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2006. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_SPLIT_HPP +#define BOOST_STRING_SPLIT_HPP + +#include <boost/algorithm/string/config.hpp> + +#include <boost/algorithm/string/iter_find.hpp> +#include <boost/algorithm/string/finder.hpp> +#include <boost/algorithm/string/compare.hpp> + +/*! \file + Defines basic split algorithms. + Split algorithms can be used to divide a string + into several parts according to given criteria. + + Each part is copied and added as a new element to the + output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector<std::string> + or \c std::list<boost::iterator_range<std::string::iterator>> +*/ + +namespace boost { + namespace algorithm { + +// find_all ------------------------------------------------------------// + + //! Find all algorithm + /*! + This algorithm finds all occurrences of the search string + in the input. + + Each part is copied and added as a new element to the + output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector<std::string> + or \c std::list<boost::iterator_range<std::string::iterator>> + + \param Result A container that can hold copies of references to the substrings + \param Input A container which will be searched. + \param Search A substring to be searched for. + \return A reference the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename Range1T, typename Range2T > + inline SequenceSequenceT& find_all( + SequenceSequenceT& Result, + Range1T& Input, + const Range2T& Search) + { + return ::boost::algorithm::iter_find( + Result, + Input, + ::boost::algorithm::first_finder(Search) ); + } + + //! Find all algorithm ( case insensitive ) + /*! + This algorithm finds all occurrences of the search string + in the input. + Each part is copied and added as a new element to the + output container. Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector<std::string> + or \c std::list<boost::iterator_range<std::string::iterator>> + + Searching is case insensitive. + + \param Result A container that can hold copies of references to the substrings + \param Input A container which will be searched. + \param Search A substring to be searched for. + \param Loc A locale used for case insensitive comparison + \return A reference the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename Range1T, typename Range2T > + inline SequenceSequenceT& ifind_all( + SequenceSequenceT& Result, + Range1T& Input, + const Range2T& Search, + const std::locale& Loc=std::locale() ) + { + return ::boost::algorithm::iter_find( + Result, + Input, + ::boost::algorithm::first_finder(Search, is_iequal(Loc) ) ); + } + + +// tokenize -------------------------------------------------------------// + + //! Split algorithm + /*! + Tokenize expression. This function is equivalent to C strtok. Input + sequence is split into tokens, separated by separators. Separators + are given by means of the predicate. + + Each part is copied and added as a new element to the + output container. + Thus the result container must be able to hold copies + of the matches (in a compatible structure like std::string) or + a reference to it (e.g. using the iterator range class). + Examples of such a container are \c std::vector<std::string> + or \c std::list<boost::iterator_range<std::string::iterator>> + + \param Result A container that can hold copies of references to the substrings + \param Input A container which will be searched. + \param Pred A predicate to identify separators. This predicate is + supposed to return true if a given element is a separator. + \param eCompress If eCompress argument is set to token_compress_on, adjacent + separators are merged together. Otherwise, every two separators + delimit a token. + \return A reference the result + + \note Prior content of the result will be overwritten. + + \note This function provides the strong exception-safety guarantee + */ + template< typename SequenceSequenceT, typename RangeT, typename PredicateT > + inline SequenceSequenceT& split( + SequenceSequenceT& Result, + RangeT& Input, + PredicateT Pred, + token_compress_mode_type eCompress=token_compress_off ) + { + return ::boost::algorithm::iter_split( + Result, + Input, + ::boost::algorithm::token_finder( Pred, eCompress ) ); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::find_all; + using algorithm::ifind_all; + using algorithm::split; + +} // namespace boost + + +#endif // BOOST_STRING_SPLIT_HPP +
diff --git a/boost/boost/algorithm/string/std/list_traits.hpp b/boost/boost/algorithm/string/std/list_traits.hpp new file mode 100644 index 0000000..a3cf7bb --- /dev/null +++ b/boost/boost/algorithm/string/std/list_traits.hpp
@@ -0,0 +1,68 @@ +// Boost string_algo library list_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_LIST_TRAITS_HPP +#define BOOST_STRING_STD_LIST_TRAITS_HPP + +#include <boost/algorithm/string/yes_no_type.hpp> +#include <list> +#include <boost/algorithm/string/sequence_traits.hpp> + +namespace boost { + namespace algorithm { + +// std::list<> traits -----------------------------------------------// + + + // stable iterators trait + template<typename T, typename AllocT> + class has_stable_iterators< ::std::list<T,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<has_stable_iterators<T>::value> type; + }; + + // const time insert trait + template<typename T, typename AllocT> + class has_const_time_insert< ::std::list<T,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<has_const_time_insert<T>::value> type; + }; + + // const time erase trait + template<typename T, typename AllocT> + class has_const_time_erase< ::std::list<T,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<has_const_time_erase<T>::value> type; + }; + + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_STD_LIST_TRAITS_HPP
diff --git a/boost/boost/algorithm/string/std/rope_traits.hpp b/boost/boost/algorithm/string/std/rope_traits.hpp new file mode 100644 index 0000000..637059a --- /dev/null +++ b/boost/boost/algorithm/string/std/rope_traits.hpp
@@ -0,0 +1,81 @@ +// Boost string_algo library string_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_ROPE_TRAITS_HPP +#define BOOST_STRING_STD_ROPE_TRAITS_HPP + +#include <boost/algorithm/string/yes_no_type.hpp> +#include <rope> +#include <boost/algorithm/string/sequence_traits.hpp> + +namespace boost { + namespace algorithm { + +// SGI's std::rope<> traits -----------------------------------------------// + + + // native replace trait + template<typename T, typename TraitsT, typename AllocT> + class has_native_replace< std::rope<T,TraitsT,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<value> type; + }; + + // stable iterators trait + template<typename T, typename TraitsT, typename AllocT> + class has_stable_iterators< std::rope<T,TraitsT,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<value> type; + }; + + // const time insert trait + template<typename T, typename TraitsT, typename AllocT> + class has_const_time_insert< std::rope<T,TraitsT,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<value> type; + }; + + // const time erase trait + template<typename T, typename TraitsT, typename AllocT> + class has_const_time_erase< std::rope<T,TraitsT,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<value> type; + }; + + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_ROPE_TRAITS_HPP
diff --git a/boost/boost/algorithm/string/std/slist_traits.hpp b/boost/boost/algorithm/string/std/slist_traits.hpp new file mode 100644 index 0000000..c30b93c --- /dev/null +++ b/boost/boost/algorithm/string/std/slist_traits.hpp
@@ -0,0 +1,69 @@ +// Boost string_algo library slist_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_SLIST_TRAITS_HPP +#define BOOST_STRING_STD_SLIST_TRAITS_HPP + +#include <boost/algorithm/string/config.hpp> +#include <boost/algorithm/string/yes_no_type.hpp> +#include BOOST_SLIST_HEADER +#include <boost/algorithm/string/sequence_traits.hpp> + +namespace boost { + namespace algorithm { + +// SGI's std::slist<> traits -----------------------------------------------// + + + // stable iterators trait + template<typename T, typename AllocT> + class has_stable_iterators< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<has_stable_iterators<T>::value> type; + }; + + // const time insert trait + template<typename T, typename AllocT> + class has_const_time_insert< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<has_const_time_insert<T>::value> type; + }; + + // const time erase trait + template<typename T, typename AllocT> + class has_const_time_erase< BOOST_STD_EXTENSION_NAMESPACE::slist<T,AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true }; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + typedef mpl::bool_<has_const_time_erase<T>::value> type; + }; + + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_STD_LIST_TRAITS_HPP
diff --git a/boost/boost/algorithm/string/std/string_traits.hpp b/boost/boost/algorithm/string/std/string_traits.hpp new file mode 100644 index 0000000..c940830 --- /dev/null +++ b/boost/boost/algorithm/string/std/string_traits.hpp
@@ -0,0 +1,44 @@ +// Boost string_algo library string_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_STRING_TRAITS_HPP +#define BOOST_STRING_STD_STRING_TRAITS_HPP + +#include <boost/algorithm/string/yes_no_type.hpp> +#include <string> +#include <boost/algorithm/string/sequence_traits.hpp> + +namespace boost { + namespace algorithm { + +// std::basic_string<> traits -----------------------------------------------// + + + // native replace trait + template<typename T, typename TraitsT, typename AllocT> + class has_native_replace< std::basic_string<T, TraitsT, AllocT> > + { + public: +#if BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + enum { value = true } ; +#else + BOOST_STATIC_CONSTANT(bool, value=true); +#endif // BOOST_WORKAROUND( __IBMCPP__, <= 600 ) + + typedef mpl::bool_<has_native_replace<T>::value> type; + }; + + + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_LIST_TRAITS_HPP
diff --git a/boost/boost/algorithm/string/std_containers_traits.hpp b/boost/boost/algorithm/string/std_containers_traits.hpp new file mode 100644 index 0000000..3f02246 --- /dev/null +++ b/boost/boost/algorithm/string/std_containers_traits.hpp
@@ -0,0 +1,26 @@ +// Boost string_algo library std_containers_traits.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_STD_CONTAINERS_TRAITS_HPP +#define BOOST_STRING_STD_CONTAINERS_TRAITS_HPP + +/*!\file + This file includes sequence traits for stl containers. +*/ + +#include <boost/config.hpp> +#include <boost/algorithm/string/std/string_traits.hpp> +#include <boost/algorithm/string/std/list_traits.hpp> + +#ifdef BOOST_HAS_SLIST +# include <boost/algorithm/string/std/slist_traits.hpp> +#endif + +#endif // BOOST_STRING_STD_CONTAINERS_TRAITS_HPP
diff --git a/boost/boost/algorithm/string/trim.hpp b/boost/boost/algorithm/string/trim.hpp new file mode 100644 index 0000000..e740d57 --- /dev/null +++ b/boost/boost/algorithm/string/trim.hpp
@@ -0,0 +1,398 @@ +// Boost string_algo library trim.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_TRIM_HPP +#define BOOST_STRING_TRIM_HPP + +#include <boost/algorithm/string/config.hpp> + +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/const_iterator.hpp> +#include <boost/range/as_literal.hpp> +#include <boost/range/iterator_range_core.hpp> + +#include <boost/algorithm/string/detail/trim.hpp> +#include <boost/algorithm/string/classification.hpp> +#include <locale> + +/*! \file + Defines trim algorithms. + Trim algorithms are used to remove trailing and leading spaces from a + sequence (string). Space is recognized using given locales. + + Parametric (\c _if) variants use a predicate (functor) to select which characters + are to be trimmed.. + Functions take a selection predicate as a parameter, which is used to determine + whether a character is a space. Common predicates are provided in classification.hpp header. + +*/ + +namespace boost { + namespace algorithm { + + // left trim -----------------------------------------------// + + + //! Left trim - parametric + /*! + Remove all leading spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The result is a trimmed copy of the input. It is returned as a sequence + or copied to the output iterator + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param IsSpace A unary predicate identifying spaces + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template<typename OutputIteratorT, typename RangeT, typename PredicateT> + inline OutputIteratorT trim_left_copy_if( + OutputIteratorT Output, + const RangeT& Input, + PredicateT IsSpace) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_range(::boost::as_literal(Input)); + + std::copy( + ::boost::algorithm::detail::trim_begin( + ::boost::begin(lit_range), + ::boost::end(lit_range), + IsSpace ), + ::boost::end(lit_range), + Output); + + return Output; + } + + //! Left trim - parametric + /*! + \overload + */ + template<typename SequenceT, typename PredicateT> + inline SequenceT trim_left_copy_if(const SequenceT& Input, PredicateT IsSpace) + { + return SequenceT( + ::boost::algorithm::detail::trim_begin( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace ), + ::boost::end(Input)); + } + + //! Left trim - parametric + /*! + Remove all leading spaces from the input. + The result is a trimmed copy of the input. + + \param Input An input sequence + \param Loc a locale used for 'space' classification + \return A trimmed copy of the input + + \note This function provides the strong exception-safety guarantee + */ + template<typename SequenceT> + inline SequenceT trim_left_copy(const SequenceT& Input, const std::locale& Loc=std::locale()) + { + return + ::boost::algorithm::trim_left_copy_if( + Input, + is_space(Loc)); + } + + //! Left trim + /*! + Remove all leading spaces from the input. The supplied predicate is + used to determine which characters are considered spaces. + The input sequence is modified in-place. + + \param Input An input sequence + \param IsSpace A unary predicate identifying spaces + */ + template<typename SequenceT, typename PredicateT> + inline void trim_left_if(SequenceT& Input, PredicateT IsSpace) + { + Input.erase( + ::boost::begin(Input), + ::boost::algorithm::detail::trim_begin( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace)); + } + + //! Left trim + /*! + Remove all leading spaces from the input. + The Input sequence is modified in-place. + + \param Input An input sequence + \param Loc A locale used for 'space' classification + */ + template<typename SequenceT> + inline void trim_left(SequenceT& Input, const std::locale& Loc=std::locale()) + { + ::boost::algorithm::trim_left_if( + Input, + is_space(Loc)); + } + + // right trim -----------------------------------------------// + + //! Right trim - parametric + /*! + Remove all trailing spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The result is a trimmed copy of the input. It is returned as a sequence + or copied to the output iterator + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param IsSpace A unary predicate identifying spaces + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template<typename OutputIteratorT, typename RangeT, typename PredicateT> + inline OutputIteratorT trim_right_copy_if( + OutputIteratorT Output, + const RangeT& Input, + PredicateT IsSpace ) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_range(::boost::as_literal(Input)); + + std::copy( + ::boost::begin(lit_range), + ::boost::algorithm::detail::trim_end( + ::boost::begin(lit_range), + ::boost::end(lit_range), + IsSpace ), + Output ); + + return Output; + } + + //! Right trim - parametric + /*! + \overload + */ + template<typename SequenceT, typename PredicateT> + inline SequenceT trim_right_copy_if(const SequenceT& Input, PredicateT IsSpace) + { + return SequenceT( + ::boost::begin(Input), + ::boost::algorithm::detail::trim_end( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace) + ); + } + + //! Right trim + /*! + Remove all trailing spaces from the input. + The result is a trimmed copy of the input + + \param Input An input sequence + \param Loc A locale used for 'space' classification + \return A trimmed copy of the input + + \note This function provides the strong exception-safety guarantee + */ + template<typename SequenceT> + inline SequenceT trim_right_copy(const SequenceT& Input, const std::locale& Loc=std::locale()) + { + return + ::boost::algorithm::trim_right_copy_if( + Input, + is_space(Loc)); + } + + + //! Right trim - parametric + /*! + Remove all trailing spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The input sequence is modified in-place. + + \param Input An input sequence + \param IsSpace A unary predicate identifying spaces + */ + template<typename SequenceT, typename PredicateT> + inline void trim_right_if(SequenceT& Input, PredicateT IsSpace) + { + Input.erase( + ::boost::algorithm::detail::trim_end( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace ), + ::boost::end(Input) + ); + } + + + //! Right trim + /*! + Remove all trailing spaces from the input. + The input sequence is modified in-place. + + \param Input An input sequence + \param Loc A locale used for 'space' classification + */ + template<typename SequenceT> + inline void trim_right(SequenceT& Input, const std::locale& Loc=std::locale()) + { + ::boost::algorithm::trim_right_if( + Input, + is_space(Loc) ); + } + + // both side trim -----------------------------------------------// + + //! Trim - parametric + /*! + Remove all trailing and leading spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The result is a trimmed copy of the input. It is returned as a sequence + or copied to the output iterator + + \param Output An output iterator to which the result will be copied + \param Input An input range + \param IsSpace A unary predicate identifying spaces + \return + An output iterator pointing just after the last inserted character or + a copy of the input + + \note The second variant of this function provides the strong exception-safety guarantee + */ + template<typename OutputIteratorT, typename RangeT, typename PredicateT> + inline OutputIteratorT trim_copy_if( + OutputIteratorT Output, + const RangeT& Input, + PredicateT IsSpace) + { + iterator_range<BOOST_STRING_TYPENAME range_const_iterator<RangeT>::type> lit_range(::boost::as_literal(Input)); + + BOOST_STRING_TYPENAME + range_const_iterator<RangeT>::type TrimEnd= + ::boost::algorithm::detail::trim_end( + ::boost::begin(lit_range), + ::boost::end(lit_range), + IsSpace); + + std::copy( + detail::trim_begin( + ::boost::begin(lit_range), TrimEnd, IsSpace), + TrimEnd, + Output + ); + + return Output; + } + + //! Trim - parametric + /*! + \overload + */ + template<typename SequenceT, typename PredicateT> + inline SequenceT trim_copy_if(const SequenceT& Input, PredicateT IsSpace) + { + BOOST_STRING_TYPENAME + range_const_iterator<SequenceT>::type TrimEnd= + ::boost::algorithm::detail::trim_end( + ::boost::begin(Input), + ::boost::end(Input), + IsSpace); + + return SequenceT( + detail::trim_begin( + ::boost::begin(Input), + TrimEnd, + IsSpace), + TrimEnd + ); + } + + //! Trim + /*! + Remove all leading and trailing spaces from the input. + The result is a trimmed copy of the input + + \param Input An input sequence + \param Loc A locale used for 'space' classification + \return A trimmed copy of the input + + \note This function provides the strong exception-safety guarantee + */ + template<typename SequenceT> + inline SequenceT trim_copy( const SequenceT& Input, const std::locale& Loc=std::locale() ) + { + return + ::boost::algorithm::trim_copy_if( + Input, + is_space(Loc) ); + } + + //! Trim + /*! + Remove all leading and trailing spaces from the input. + The supplied predicate is used to determine which characters are considered spaces. + The input sequence is modified in-place. + + \param Input An input sequence + \param IsSpace A unary predicate identifying spaces + */ + template<typename SequenceT, typename PredicateT> + inline void trim_if(SequenceT& Input, PredicateT IsSpace) + { + ::boost::algorithm::trim_right_if( Input, IsSpace ); + ::boost::algorithm::trim_left_if( Input, IsSpace ); + } + + //! Trim + /*! + Remove all leading and trailing spaces from the input. + The input sequence is modified in-place. + + \param Input An input sequence + \param Loc A locale used for 'space' classification + */ + template<typename SequenceT> + inline void trim(SequenceT& Input, const std::locale& Loc=std::locale()) + { + ::boost::algorithm::trim_if( + Input, + is_space( Loc ) ); + } + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::trim_left; + using algorithm::trim_left_if; + using algorithm::trim_left_copy; + using algorithm::trim_left_copy_if; + using algorithm::trim_right; + using algorithm::trim_right_if; + using algorithm::trim_right_copy; + using algorithm::trim_right_copy_if; + using algorithm::trim; + using algorithm::trim_if; + using algorithm::trim_copy; + using algorithm::trim_copy_if; + +} // namespace boost + +#endif // BOOST_STRING_TRIM_HPP
diff --git a/boost/boost/algorithm/string/trim_all.hpp b/boost/boost/algorithm/string/trim_all.hpp new file mode 100644 index 0000000..a616f7f --- /dev/null +++ b/boost/boost/algorithm/string/trim_all.hpp
@@ -0,0 +1,217 @@ +// Boost string_algo library trim.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_TRIM_ALL_HPP +#define BOOST_STRING_TRIM_ALL_HPP + +#include <boost/algorithm/string/config.hpp> + +#include <boost/algorithm/string/trim.hpp> +#include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/find_format.hpp> +#include <boost/algorithm/string/formatter.hpp> +#include <boost/algorithm/string/finder.hpp> +#include <locale> + +/*! \file + Defines trim_all algorithms. + + Just like \c trim, \c trim_all removes all trailing and leading spaces from a + sequence (string). In addition, spaces in the middle of the sequence are truncated + to just one character. Space is recognized using given locales. + + \c trim_fill acts as trim_all, but the spaces in the middle are replaces with + a user-define sequence of character. + + Parametric (\c _if) variants use a predicate (functor) to select which characters + are to be trimmed.. + Functions take a selection predicate as a parameter, which is used to determine + whether a character is a space. Common predicates are provided in classification.hpp header. + +*/ + +namespace boost { + namespace algorithm { + + // multi line trim ----------------------------------------------- // + + //! Trim All - parametric + /*! + Remove all leading and trailing spaces from the input and + compress all other spaces to a single character. + The result is a trimmed copy of the input + + \param Input An input sequence + \param IsSpace A unary predicate identifying spaces + \return A trimmed copy of the input + */ + template<typename SequenceT, typename PredicateT> + inline SequenceT trim_all_copy_if(const SequenceT& Input, PredicateT IsSpace) + { + return + ::boost::find_format_all_copy( + ::boost::trim_copy_if(Input, IsSpace), + ::boost::token_finder(IsSpace, ::boost::token_compress_on), + ::boost::dissect_formatter(::boost::head_finder(1))); + } + + + //! Trim All + /*! + Remove all leading and trailing spaces from the input and + compress all other spaces to a single character. + The input sequence is modified in-place. + + \param Input An input sequence + \param IsSpace A unary predicate identifying spaces + */ + template<typename SequenceT, typename PredicateT> + inline void trim_all_if(SequenceT& Input, PredicateT IsSpace) + { + ::boost::trim_if(Input, IsSpace); + ::boost::find_format_all( + Input, + ::boost::token_finder(IsSpace, ::boost::token_compress_on), + ::boost::dissect_formatter(::boost::head_finder(1))); + } + + + //! Trim All + /*! + Remove all leading and trailing spaces from the input and + compress all other spaces to a single character. + The result is a trimmed copy of the input + + \param Input An input sequence + \param Loc A locale used for 'space' classification + \return A trimmed copy of the input + */ + template<typename SequenceT> + inline SequenceT trim_all_copy(const SequenceT& Input, const std::locale& Loc =std::locale()) + { + return trim_all_copy_if(Input, ::boost::is_space(Loc)); + } + + + //! Trim All + /*! + Remove all leading and trailing spaces from the input and + compress all other spaces to a single character. + The input sequence is modified in-place. + + \param Input An input sequence + \param Loc A locale used for 'space' classification + \return A trimmed copy of the input + */ + template<typename SequenceT> + inline void trim_all(SequenceT& Input, const std::locale& Loc =std::locale()) + { + trim_all_if(Input, ::boost::is_space(Loc)); + } + + + //! Trim Fill - parametric + /*! + Remove all leading and trailing spaces from the input and + replace all every block of consecutive spaces with a fill string + defined by user. + The result is a trimmed copy of the input + + \param Input An input sequence + \param Fill A string used to fill the inner spaces + \param IsSpace A unary predicate identifying spaces + \return A trimmed copy of the input + */ + template<typename SequenceT, typename RangeT, typename PredicateT> + inline SequenceT trim_fill_copy_if(const SequenceT& Input, const RangeT& Fill, PredicateT IsSpace) + { + return + ::boost::find_format_all_copy( + ::boost::trim_copy_if(Input, IsSpace), + ::boost::token_finder(IsSpace, ::boost::token_compress_on), + ::boost::const_formatter(::boost::as_literal(Fill))); + } + + + //! Trim Fill + /*! + Remove all leading and trailing spaces from the input and + replace all every block of consecutive spaces with a fill string + defined by user. + The input sequence is modified in-place. + + \param Input An input sequence + \param Fill A string used to fill the inner 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) + { + ::boost::trim_if(Input, IsSpace); + ::boost::find_format_all( + Input, + ::boost::token_finder(IsSpace, ::boost::token_compress_on), + ::boost::const_formatter(::boost::as_literal(Fill))); + } + + + //! Trim Fill + /*! + Remove all leading and trailing spaces from the input and + replace all every block of consecutive spaces with a fill string + defined by user. + The result is a trimmed copy of the input + + \param Input An input sequence + \param Fill A string used to fill the inner spaces + \param Loc A locale used for 'space' classification + \return A trimmed copy of the input + */ + template<typename SequenceT, typename RangeT> + inline SequenceT trim_fill_copy(const SequenceT& Input, const RangeT& Fill, const std::locale& Loc =std::locale()) + { + return trim_fill_copy_if(Input, Fill, ::boost::is_space(Loc)); + } + + + //! Trim Fill + /*! + Remove all leading and trailing spaces from the input and + replace all every block of consecutive spaces with a fill string + defined by user. + The input sequence is modified in-place. + + \param Input An input sequence + \param Fill A string used to fill the inner spaces + \param Loc A locale used for 'space' classification + \return A trimmed copy of the input + */ + template<typename SequenceT, typename RangeT> + inline void trim_fill(SequenceT& Input, const RangeT& Fill, const std::locale& Loc =std::locale()) + { + trim_fill_if(Input, Fill, ::boost::is_space(Loc)); + } + + + } // namespace algorithm + + // pull names to the boost namespace + using algorithm::trim_all; + using algorithm::trim_all_if; + using algorithm::trim_all_copy; + using algorithm::trim_all_copy_if; + using algorithm::trim_fill; + using algorithm::trim_fill_if; + using algorithm::trim_fill_copy; + using algorithm::trim_fill_copy_if; + +} // namespace boost + +#endif // BOOST_STRING_TRIM_ALL_HPP
diff --git a/boost/boost/algorithm/string/yes_no_type.hpp b/boost/boost/algorithm/string/yes_no_type.hpp new file mode 100644 index 0000000..b76cc6c --- /dev/null +++ b/boost/boost/algorithm/string/yes_no_type.hpp
@@ -0,0 +1,33 @@ +// Boost string_algo library yes_no_type.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2003. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_YES_NO_TYPE_DETAIL_HPP +#define BOOST_STRING_YES_NO_TYPE_DETAIL_HPP + +namespace boost { + namespace algorithm { + + // taken from boost mailing-list + // when yes_no_type will become officially + // a part of boost distribution, this header + // will be deprecated + template<int I> struct size_descriptor + { + typedef char (& type)[I]; + }; + + typedef size_descriptor<1>::type yes_type; + typedef size_descriptor<2>::type no_type; + + } // namespace algorithm +} // namespace boost + + +#endif // BOOST_STRING_YES_NO_TYPE_DETAIL_HPP
diff --git a/boost/boost/algorithm/string_regex.hpp b/boost/boost/algorithm/string_regex.hpp new file mode 100644 index 0000000..791aa18 --- /dev/null +++ b/boost/boost/algorithm/string_regex.hpp
@@ -0,0 +1,23 @@ +// Boost string_algo library string_regex.hpp header file ---------------------------// + +// Copyright Pavol Droba 2002-2004. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org/ for updates, documentation, and revision history. + +#ifndef BOOST_STRING_ALGO_REGEX_HPP +#define BOOST_STRING_ALGO_REGEX_HPP + +/*! \file + Cumulative include for string_algo library. + In addition to string.hpp contains also regex-related stuff. +*/ + +#include <boost/regex.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/regex.hpp> + +#endif // BOOST_STRING_ALGO_REGEX_HPP
diff --git a/boost/boost/align.hpp b/boost/boost/align.hpp new file mode 100644 index 0000000..d5ae6d3 --- /dev/null +++ b/boost/boost/align.hpp
@@ -0,0 +1,20 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_HPP +#define BOOST_ALIGN_HPP + +#include <boost/align/align.hpp> +#include <boost/align/aligned_alloc.hpp> +#include <boost/align/aligned_allocator.hpp> +#include <boost/align/aligned_allocator_adaptor.hpp> +#include <boost/align/aligned_delete.hpp> +#include <boost/align/alignment_of.hpp> +#include <boost/align/is_aligned.hpp> + +#endif
diff --git a/boost/boost/align/align.hpp b/boost/boost/align/align.hpp new file mode 100644 index 0000000..1600a24 --- /dev/null +++ b/boost/boost/align/align.hpp
@@ -0,0 +1,20 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGN_HPP +#define BOOST_ALIGN_ALIGN_HPP + +#include <boost/config.hpp> + +#if !defined(BOOST_NO_CXX11_STD_ALIGN) +#include <boost/align/detail/align_cxx11.hpp> +#else +#include <boost/align/detail/align.hpp> +#endif + +#endif
diff --git a/boost/boost/align/aligned_alloc.hpp b/boost/boost/align/aligned_alloc.hpp new file mode 100644 index 0000000..1e4f2b7 --- /dev/null +++ b/boost/boost/align/aligned_alloc.hpp
@@ -0,0 +1,42 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGNED_ALLOC_HPP +#define BOOST_ALIGN_ALIGNED_ALLOC_HPP + +#include <boost/config.hpp> + +#if defined(BOOST_HAS_UNISTD_H) +#include <unistd.h> +#endif + +#if defined(__APPLE__) || defined(__APPLE_CC__) || defined(macintosh) +#include <AvailabilityMacros.h> +#endif + +#if defined(_MSC_VER) +#include <boost/align/detail/aligned_alloc_msvc.hpp> +#elif defined(__MINGW32__) && (__MSVCRT_VERSION__ >= 0x0700) +#include <boost/align/detail/aligned_alloc_msvc.hpp> +#elif MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +#include <boost/align/detail/aligned_alloc_posix.hpp> +#elif MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 +#include <boost/align/detail/aligned_alloc_macos.hpp> +#elif defined(__ANDROID__) +#include <boost/align/detail/aligned_alloc_android.hpp> +#elif defined(__SunOS_5_11) || defined(__SunOS_5_12) +#include <boost/align/detail/aligned_alloc_posix.hpp> +#elif defined(sun) || defined(__sun) +#include <boost/align/detail/aligned_alloc_sunos.hpp> +#elif (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600) +#include <boost/align/detail/aligned_alloc_posix.hpp> +#else +#include <boost/align/detail/aligned_alloc.hpp> +#endif + +#endif
diff --git a/boost/boost/align/aligned_allocator.hpp b/boost/boost/align/aligned_allocator.hpp new file mode 100644 index 0000000..114e37b --- /dev/null +++ b/boost/boost/align/aligned_allocator.hpp
@@ -0,0 +1,168 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP +#define BOOST_ALIGN_ALIGNED_ALLOCATOR_HPP + +#include <boost/config.hpp> +#include <boost/static_assert.hpp> +#include <boost/throw_exception.hpp> +#include <boost/align/aligned_alloc.hpp> +#include <boost/align/aligned_allocator_forward.hpp> +#include <boost/align/alignment_of.hpp> +#include <boost/align/detail/addressof.hpp> +#include <boost/align/detail/is_alignment_constant.hpp> +#include <boost/align/detail/max_align.hpp> +#include <boost/align/detail/max_count_of.hpp> +#include <new> + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#include <utility> +#endif + +namespace boost { + namespace alignment { + template<class T, std::size_t Alignment> + class aligned_allocator { + BOOST_STATIC_ASSERT(detail:: + is_alignment_constant<Alignment>::value); + + public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T& reference; + typedef const T& const_reference; + + private: + typedef detail::max_align<Alignment, + alignment_of<value_type>::value> MaxAlign; + + public: + template<class U> + struct rebind { + typedef aligned_allocator<U, Alignment> other; + }; + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + aligned_allocator() + BOOST_NOEXCEPT = default; +#else + aligned_allocator() + BOOST_NOEXCEPT { + } +#endif + + template<class U> + aligned_allocator(const aligned_allocator<U, + Alignment>&) BOOST_NOEXCEPT { + } + + pointer address(reference value) const + BOOST_NOEXCEPT { + return detail::addressof(value); + } + + const_pointer address(const_reference value) const + BOOST_NOEXCEPT { + return detail::addressof(value); + } + + pointer allocate(size_type size, + const_void_pointer = 0) { + void* p = aligned_alloc(MaxAlign::value, + sizeof(T) * size); + if (!p && size > 0) { + boost::throw_exception(std::bad_alloc()); + } + return static_cast<T*>(p); + } + + void deallocate(pointer ptr, size_type) { + alignment::aligned_free(ptr); + } + + BOOST_CONSTEXPR size_type max_size() const + BOOST_NOEXCEPT { + return detail::max_count_of<T>::value; + } + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template<class U, class... Args> + void construct(U* ptr, Args&&... args) { + void* p = ptr; + ::new(p) U(std::forward<Args>(args)...); + } +#else + template<class U, class V> + void construct(U* ptr, V&& value) { + void* p = ptr; + ::new(p) U(std::forward<V>(value)); + } +#endif +#else + template<class U, class V> + void construct(U* ptr, const V& value) { + void* p = ptr; + ::new(p) U(value); + } +#endif + + template<class U> + void construct(U* ptr) { + void* p = ptr; + ::new(p) U(); + } + + template<class U> + void destroy(U* ptr) { + (void)ptr; + ptr->~U(); + } + }; + + template<std::size_t Alignment> + class aligned_allocator<void, Alignment> { + BOOST_STATIC_ASSERT(detail:: + is_alignment_constant<Alignment>::value); + + public: + typedef void value_type; + typedef void* pointer; + typedef const void* const_pointer; + + template<class U> + struct rebind { + typedef aligned_allocator<U, Alignment> other; + }; + }; + + template<class T1, class T2, std::size_t Alignment> + inline bool operator==(const aligned_allocator<T1, + Alignment>&, const aligned_allocator<T2, + Alignment>&) BOOST_NOEXCEPT + { + return true; + } + + template<class T1, class T2, std::size_t Alignment> + inline bool operator!=(const aligned_allocator<T1, + Alignment>&, const aligned_allocator<T2, + Alignment>&) BOOST_NOEXCEPT + { + return false; + } + } +} + +#endif
diff --git a/boost/boost/align/aligned_allocator_adaptor.hpp b/boost/boost/align/aligned_allocator_adaptor.hpp new file mode 100644 index 0000000..f6e0bef --- /dev/null +++ b/boost/boost/align/aligned_allocator_adaptor.hpp
@@ -0,0 +1,187 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP +#define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_HPP + +#include <boost/config.hpp> +#include <boost/static_assert.hpp> +#include <boost/align/align.hpp> +#include <boost/align/aligned_allocator_adaptor_forward.hpp> +#include <boost/align/alignment_of.hpp> +#include <boost/align/detail/addressof.hpp> +#include <boost/align/detail/is_alignment_constant.hpp> +#include <boost/align/detail/max_align.hpp> +#include <new> + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#include <memory> +#endif + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#include <utility> +#endif + +namespace boost { + namespace alignment { + template<class Allocator, std::size_t Alignment> + class aligned_allocator_adaptor + : public Allocator { + BOOST_STATIC_ASSERT(detail:: + is_alignment_constant<Alignment>::value); + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef std::allocator_traits<Allocator> Traits; + + typedef typename Traits:: + template rebind_alloc<char> CharAlloc; + + typedef typename Traits:: + template rebind_traits<char> CharTraits; + + typedef typename CharTraits::pointer CharPtr; +#else + typedef typename Allocator:: + template rebind<char>::other CharAlloc; + + typedef typename CharAlloc::pointer CharPtr; +#endif + + public: +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename Traits::value_type value_type; + typedef typename Traits::size_type size_type; +#else + typedef typename Allocator::value_type value_type; + typedef typename Allocator::size_type size_type; +#endif + + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef void* void_pointer; + typedef const void* const_void_pointer; + typedef std::ptrdiff_t difference_type; + + private: + typedef detail::max_align<Alignment, + detail::max_align<alignment_of<value_type>::value, + alignment_of<CharPtr>::value>::value> MaxAlign; + + public: + template<class U> + struct rebind { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef aligned_allocator_adaptor<typename Traits:: + template rebind_alloc<U>, Alignment> other; +#else + typedef aligned_allocator_adaptor<typename Allocator:: + template rebind<U>::other, Alignment> other; +#endif + }; + +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + aligned_allocator_adaptor() = default; +#else + aligned_allocator_adaptor() + : Allocator() { + } +#endif + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template<class A> + explicit aligned_allocator_adaptor(A&& alloc) + BOOST_NOEXCEPT + : Allocator(std::forward<A>(alloc)) { + } +#else + template<class A> + explicit aligned_allocator_adaptor(const A& alloc) + BOOST_NOEXCEPT + : Allocator(alloc) { + } +#endif + + template<class U> + aligned_allocator_adaptor(const + aligned_allocator_adaptor<U, Alignment>& other) + BOOST_NOEXCEPT + : Allocator(other.base()) { + } + + Allocator& base() + BOOST_NOEXCEPT { + return static_cast<Allocator&>(*this); + } + + const Allocator& base() const + BOOST_NOEXCEPT { + return static_cast<const Allocator&>(*this); + } + + pointer allocate(size_type size) { + std::size_t n1 = size * sizeof(value_type); + std::size_t n2 = n1 + MaxAlign::value - 1; + CharAlloc a(base()); + CharPtr p1 = a.allocate(sizeof p1 + n2); + void* p2 = detail::addressof(*p1) + sizeof p1; + (void)align(MaxAlign::value, n1, p2, n2); + void* p3 = static_cast<CharPtr*>(p2) - 1; + ::new(p3) CharPtr(p1); + return static_cast<pointer>(p2); + } + + pointer allocate(size_type size, const_void_pointer hint) { + std::size_t n1 = size * sizeof(value_type); + std::size_t n2 = n1 + MaxAlign::value - 1; + CharPtr h = CharPtr(); + if (hint) { + h = *(static_cast<const CharPtr*>(hint) - 1); + } + CharAlloc a(base()); +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + CharPtr p1 = CharTraits::allocate(a, sizeof p1 + + n2, h); +#else + CharPtr p1 = a.allocate(sizeof p1 + n2, h); +#endif + void* p2 = detail::addressof(*p1) + sizeof p1; + (void)align(MaxAlign::value, n1, p2, n2); + void* p3 = static_cast<CharPtr*>(p2) - 1; + ::new(p3) CharPtr(p1); + return static_cast<pointer>(p2); + } + + void deallocate(pointer ptr, size_type size) { + CharPtr* p1 = reinterpret_cast<CharPtr*>(ptr) - 1; + CharPtr p2 = *p1; + p1->~CharPtr(); + CharAlloc a(base()); + a.deallocate(p2, size * sizeof(value_type) + + MaxAlign::value + sizeof p2); + } + }; + + template<class A1, class A2, std::size_t Alignment> + inline bool operator==(const aligned_allocator_adaptor<A1, + Alignment>& a, const aligned_allocator_adaptor<A2, + Alignment>& b) BOOST_NOEXCEPT + { + return a.base() == b.base(); + } + + template<class A1, class A2, std::size_t Alignment> + inline bool operator!=(const aligned_allocator_adaptor<A1, + Alignment>& a, const aligned_allocator_adaptor<A2, + Alignment>& b) BOOST_NOEXCEPT + { + return !(a == b); + } + } +} + +#endif
diff --git a/boost/boost/align/aligned_allocator_adaptor_forward.hpp b/boost/boost/align/aligned_allocator_adaptor_forward.hpp new file mode 100644 index 0000000..2bd8dee --- /dev/null +++ b/boost/boost/align/aligned_allocator_adaptor_forward.hpp
@@ -0,0 +1,21 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_FORWARD_HPP +#define BOOST_ALIGN_ALIGNED_ALLOCATOR_ADAPTOR_FORWARD_HPP + +#include <cstddef> + +namespace boost { + namespace alignment { + template<class Allocator, std::size_t Alignment = 1> + class aligned_allocator_adaptor; + } +} + +#endif
diff --git a/boost/boost/align/aligned_allocator_forward.hpp b/boost/boost/align/aligned_allocator_forward.hpp new file mode 100644 index 0000000..48120e2 --- /dev/null +++ b/boost/boost/align/aligned_allocator_forward.hpp
@@ -0,0 +1,21 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGNED_ALLOCATOR_FORWARD_HPP +#define BOOST_ALIGN_ALIGNED_ALLOCATOR_FORWARD_HPP + +#include <cstddef> + +namespace boost { + namespace alignment { + template<class T, std::size_t Alignment = 1> + class aligned_allocator; + } +} + +#endif
diff --git a/boost/boost/align/aligned_delete.hpp b/boost/boost/align/aligned_delete.hpp new file mode 100644 index 0000000..479fbb1 --- /dev/null +++ b/boost/boost/align/aligned_delete.hpp
@@ -0,0 +1,32 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGNED_DELETE_HPP +#define BOOST_ALIGN_ALIGNED_DELETE_HPP + +#include <boost/config.hpp> +#include <boost/align/aligned_alloc.hpp> +#include <boost/align/aligned_delete_forward.hpp> + +namespace boost { + namespace alignment { + class aligned_delete { + public: + template<class T> + void operator()(T* ptr) const + BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(ptr->~T())) { + if (ptr) { + ptr->~T(); + alignment::aligned_free(ptr); + } + } + }; + } +} + +#endif
diff --git a/boost/boost/align/aligned_delete_forward.hpp b/boost/boost/align/aligned_delete_forward.hpp new file mode 100644 index 0000000..9392025 --- /dev/null +++ b/boost/boost/align/aligned_delete_forward.hpp
@@ -0,0 +1,18 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGNED_DELETE_FORWARD_HPP +#define BOOST_ALIGN_ALIGNED_DELETE_FORWARD_HPP + +namespace boost { + namespace alignment { + class aligned_delete; + } +} + +#endif
diff --git a/boost/boost/align/alignment_of.hpp b/boost/boost/align/alignment_of.hpp new file mode 100644 index 0000000..1862f0f --- /dev/null +++ b/boost/boost/align/alignment_of.hpp
@@ -0,0 +1,49 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGNMENT_OF_HPP +#define BOOST_ALIGN_ALIGNMENT_OF_HPP + +#include <boost/config.hpp> +#include <boost/align/alignment_of_forward.hpp> +#include <boost/align/detail/remove_traits.hpp> + +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include <boost/align/detail/alignment_of_cxx11.hpp> +#elif defined(BOOST_MSVC) +#include <boost/align/detail/alignment_of_msvc.hpp> +#elif defined(BOOST_CLANG) +#include <boost/align/detail/alignment_of_clang.hpp> +#elif defined(__ghs__) && (__GHS_VERSION_NUMBER >= 600) +#include <boost/align/detail/alignment_of_gcc.hpp> +#elif defined(__CODEGEARC__) +#include <boost/align/detail/alignment_of_codegear.hpp> +#elif defined(__GNUC__) && defined(__unix__) && !defined(__LP64__) +#include <boost/align/detail/alignment_of.hpp> +#elif __GNUC__ > 4 +#include <boost/align/detail/alignment_of_gcc.hpp> +#elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 3) +#include <boost/align/detail/alignment_of_gcc.hpp> +#else +#include <boost/align/detail/alignment_of.hpp> +#endif + +namespace boost { + namespace alignment { + template<class T> + struct alignment_of + : detail::alignment_of<typename + detail::remove_cv<typename + detail::remove_all_extents<typename + detail::remove_reference<T>:: + type>::type>::type>::type { + }; + } +} + +#endif
diff --git a/boost/boost/align/alignment_of_forward.hpp b/boost/boost/align/alignment_of_forward.hpp new file mode 100644 index 0000000..47785e2 --- /dev/null +++ b/boost/boost/align/alignment_of_forward.hpp
@@ -0,0 +1,19 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_ALIGNMENT_OF_FORWARD_HPP +#define BOOST_ALIGN_ALIGNMENT_OF_FORWARD_HPP + +namespace boost { + namespace alignment { + template<class T> + struct alignment_of; + } +} + +#endif
diff --git a/boost/boost/align/detail/address.hpp b/boost/boost/align/detail/address.hpp new file mode 100644 index 0000000..a4f3a6e --- /dev/null +++ b/boost/boost/align/detail/address.hpp
@@ -0,0 +1,27 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ADDRESS_HPP +#define BOOST_ALIGN_DETAIL_ADDRESS_HPP + +#include <boost/cstdint.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + namespace detail { +#if defined(BOOST_HAS_INTPTR_T) + typedef boost::uintptr_t address_t; +#else + typedef std::size_t address_t; +#endif + } + } +} + +#endif
diff --git a/boost/boost/align/detail/addressof.hpp b/boost/boost/align/detail/addressof.hpp new file mode 100644 index 0000000..d9d6f78 --- /dev/null +++ b/boost/boost/align/detail/addressof.hpp
@@ -0,0 +1,32 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ADDRESSOF_HPP +#define BOOST_ALIGN_DETAIL_ADDRESSOF_HPP + +#include <boost/config.hpp> + +#if !defined(BOOST_NO_CXX11_ADDRESSOF) +#include <memory> +#else +#include <boost/core/addressof.hpp> +#endif + +namespace boost { + namespace alignment { + namespace detail { +#if !defined(BOOST_NO_CXX11_ADDRESSOF) + using std::addressof; +#else + using boost::addressof; +#endif + } + } +} + +#endif
diff --git a/boost/boost/align/detail/align.hpp b/boost/boost/align/detail/align.hpp new file mode 100644 index 0000000..e3a90df --- /dev/null +++ b/boost/boost/align/detail/align.hpp
@@ -0,0 +1,38 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGN_HPP +#define BOOST_ALIGN_DETAIL_ALIGN_HPP + +#include <boost/assert.hpp> +#include <boost/align/detail/address.hpp> +#include <boost/align/detail/is_alignment.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + inline void* align(std::size_t alignment, std::size_t size, + void*& ptr, std::size_t& space) + { + BOOST_ASSERT(detail::is_alignment(alignment)); + std::size_t n = detail::address_t(ptr) & (alignment - 1); + if (n != 0) { + n = alignment - n; + } + void* p = 0; + if (n <= space && size <= space - n) { + p = static_cast<char*>(ptr) + n; + ptr = p; + space -= n; + } + return p; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/align_cxx11.hpp b/boost/boost/align/detail/align_cxx11.hpp new file mode 100644 index 0000000..6672a7e --- /dev/null +++ b/boost/boost/align/detail/align_cxx11.hpp
@@ -0,0 +1,20 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGN_CXX11_HPP +#define BOOST_ALIGN_DETAIL_ALIGN_CXX11_HPP + +#include <memory> + +namespace boost { + namespace alignment { + using std::align; + } +} + +#endif
diff --git a/boost/boost/align/detail/aligned_alloc.hpp b/boost/boost/align/detail/aligned_alloc.hpp new file mode 100644 index 0000000..147b0de --- /dev/null +++ b/boost/boost/align/detail/aligned_alloc.hpp
@@ -0,0 +1,50 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_HPP + +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/align/align.hpp> +#include <boost/align/alignment_of.hpp> +#include <boost/align/detail/is_alignment.hpp> +#include <cstdlib> + +namespace boost { + namespace alignment { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) BOOST_NOEXCEPT + { + BOOST_ASSERT(detail::is_alignment(alignment)); + if (alignment < alignment_of<void*>::value) { + alignment = alignment_of<void*>::value; + } + std::size_t n = size + alignment - 1; + void* p1 = 0; + void* p2 = std::malloc(n + sizeof p1); + if (p2) { + p1 = static_cast<char*>(p2) + sizeof p1; + (void)align(alignment, size, p1, n); + *(static_cast<void**>(p1) - 1) = p2; + } + return p1; + } + + inline void aligned_free(void* ptr) + BOOST_NOEXCEPT + { + if (ptr) { + void* p = *(static_cast<void**>(ptr) - 1); + std::free(p); + } + } + } +} + +#endif
diff --git a/boost/boost/align/detail/aligned_alloc_android.hpp b/boost/boost/align/detail/aligned_alloc_android.hpp new file mode 100644 index 0000000..2b813be --- /dev/null +++ b/boost/boost/align/detail/aligned_alloc_android.hpp
@@ -0,0 +1,35 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_ANDROID_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_ANDROID_HPP + +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/align/detail/is_alignment.hpp> +#include <cstddef> +#include <malloc.h> + +namespace boost { + namespace alignment { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) BOOST_NOEXCEPT + { + BOOST_ASSERT(detail::is_alignment(alignment)); + return ::memalign(alignment, size); + } + + inline void aligned_free(void* ptr) + BOOST_NOEXCEPT + { + ::free(ptr); + } + } +} + +#endif
diff --git a/boost/boost/align/detail/aligned_alloc_macos.hpp b/boost/boost/align/detail/aligned_alloc_macos.hpp new file mode 100644 index 0000000..346eabf --- /dev/null +++ b/boost/boost/align/detail/aligned_alloc_macos.hpp
@@ -0,0 +1,45 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MACOS_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MACOS_HPP + +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/align/detail/is_alignment.hpp> +#include <cstddef> +#include <stdlib.h> + +namespace boost { + namespace alignment { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) BOOST_NOEXCEPT + { + BOOST_ASSERT(detail::is_alignment(alignment)); + if (!size) { + return 0; + } + if (alignment < sizeof(void*)) { + alignment = sizeof(void*); + } + void* p; + if (::posix_memalign(&p, alignment, size) != 0) { + p = 0; + } + return p; + } + + inline void aligned_free(void* ptr) + BOOST_NOEXCEPT + { + ::free(ptr); + } + } +} + +#endif
diff --git a/boost/boost/align/detail/aligned_alloc_msvc.hpp b/boost/boost/align/detail/aligned_alloc_msvc.hpp new file mode 100644 index 0000000..570a898 --- /dev/null +++ b/boost/boost/align/detail/aligned_alloc_msvc.hpp
@@ -0,0 +1,35 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MSVC_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_MSVC_HPP + +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/align/detail/is_alignment.hpp> +#include <cstddef> +#include <malloc.h> + +namespace boost { + namespace alignment { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) BOOST_NOEXCEPT + { + BOOST_ASSERT(detail::is_alignment(alignment)); + return ::_aligned_malloc(size, alignment); + } + + inline void aligned_free(void* ptr) + BOOST_NOEXCEPT + { + ::_aligned_free(ptr); + } + } +} + +#endif
diff --git a/boost/boost/align/detail/aligned_alloc_posix.hpp b/boost/boost/align/detail/aligned_alloc_posix.hpp new file mode 100644 index 0000000..ceab4cb --- /dev/null +++ b/boost/boost/align/detail/aligned_alloc_posix.hpp
@@ -0,0 +1,42 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_POSIX_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_POSIX_HPP + +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/align/detail/is_alignment.hpp> +#include <cstddef> +#include <stdlib.h> + +namespace boost { + namespace alignment { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) BOOST_NOEXCEPT + { + BOOST_ASSERT(detail::is_alignment(alignment)); + if (alignment < sizeof(void*)) { + alignment = sizeof(void*); + } + void* p; + if (::posix_memalign(&p, alignment, size) != 0) { + p = 0; + } + return p; + } + + inline void aligned_free(void* ptr) + BOOST_NOEXCEPT + { + ::free(ptr); + } + } +} + +#endif
diff --git a/boost/boost/align/detail/aligned_alloc_sunos.hpp b/boost/boost/align/detail/aligned_alloc_sunos.hpp new file mode 100644 index 0000000..a2373bd --- /dev/null +++ b/boost/boost/align/detail/aligned_alloc_sunos.hpp
@@ -0,0 +1,35 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_SUNOS_HPP +#define BOOST_ALIGN_DETAIL_ALIGNED_ALLOC_SUNOS_HPP + +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/align/detail/is_alignment.hpp> +#include <cstddef> +#include <stdlib.h> + +namespace boost { + namespace alignment { + inline void* aligned_alloc(std::size_t alignment, + std::size_t size) BOOST_NOEXCEPT + { + BOOST_ASSERT(detail::is_alignment(alignment)); + return ::memalign(alignment, size); + } + + inline void aligned_free(void* ptr) + BOOST_NOEXCEPT + { + ::free(ptr); + } + } +} + +#endif
diff --git a/boost/boost/align/detail/alignment_of.hpp b/boost/boost/align/detail/alignment_of.hpp new file mode 100644 index 0000000..1fa3070 --- /dev/null +++ b/boost/boost/align/detail/alignment_of.hpp
@@ -0,0 +1,27 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_HPP +#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_HPP + +#include <boost/align/detail/min_size.hpp> +#include <boost/align/detail/offset_object.hpp> + +namespace boost { + namespace alignment { + namespace detail { + template<class T> + struct alignment_of + : min_size<sizeof(T), + sizeof(offset_object<T>) - sizeof(T)>::type { + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/alignment_of_clang.hpp b/boost/boost/align/detail/alignment_of_clang.hpp new file mode 100644 index 0000000..18d7c71 --- /dev/null +++ b/boost/boost/align/detail/alignment_of_clang.hpp
@@ -0,0 +1,26 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CLANG_HPP +#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CLANG_HPP + +#include <boost/align/detail/integral_constant.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + namespace detail { + template<class T> + struct alignment_of + : integral_constant<std::size_t, __alignof(T)> { + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/alignment_of_codegear.hpp b/boost/boost/align/detail/alignment_of_codegear.hpp new file mode 100644 index 0000000..9074967 --- /dev/null +++ b/boost/boost/align/detail/alignment_of_codegear.hpp
@@ -0,0 +1,26 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CODEGEAR_HPP +#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CODEGEAR_HPP + +#include <boost/align/detail/integral_constant.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + namespace detail { + template<class T> + struct alignment_of + : integral_constant<std::size_t, alignof(T)> { + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/alignment_of_cxx11.hpp b/boost/boost/align/detail/alignment_of_cxx11.hpp new file mode 100644 index 0000000..d5d00a0 --- /dev/null +++ b/boost/boost/align/detail/alignment_of_cxx11.hpp
@@ -0,0 +1,22 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CXX11_HPP +#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_CXX11_HPP + +#include <type_traits> + +namespace boost { + namespace alignment { + namespace detail { + using std::alignment_of; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/alignment_of_gcc.hpp b/boost/boost/align/detail/alignment_of_gcc.hpp new file mode 100644 index 0000000..3044b2a --- /dev/null +++ b/boost/boost/align/detail/alignment_of_gcc.hpp
@@ -0,0 +1,26 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_GCC_HPP +#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_GCC_HPP + +#include <boost/align/detail/integral_constant.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + namespace detail { + template<class T> + struct alignment_of + : integral_constant<std::size_t, __alignof__(T)> { + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/alignment_of_msvc.hpp b/boost/boost/align/detail/alignment_of_msvc.hpp new file mode 100644 index 0000000..a86f785 --- /dev/null +++ b/boost/boost/align/detail/alignment_of_msvc.hpp
@@ -0,0 +1,27 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_ALIGNMENT_OF_MSVC_HPP +#define BOOST_ALIGN_DETAIL_ALIGNMENT_OF_MSVC_HPP + +#include <boost/align/detail/min_size.hpp> +#include <boost/align/detail/offset_object.hpp> + +namespace boost { + namespace alignment { + namespace detail { + template<class T> + struct alignment_of + : min_size<sizeof(T), + offsetof(offset_object<T>, object)>::type { + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/integral_constant.hpp b/boost/boost/align/detail/integral_constant.hpp new file mode 100644 index 0000000..332aade --- /dev/null +++ b/boost/boost/align/detail/integral_constant.hpp
@@ -0,0 +1,46 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_INTEGRAL_CONSTANT_HPP +#define BOOST_ALIGN_DETAIL_INTEGRAL_CONSTANT_HPP + +#include <boost/config.hpp> + +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include <type_traits> +#endif + +namespace boost { + namespace alignment { + namespace detail { +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) + using std::integral_constant; +#else + template<class T, T Value> + struct integral_constant { + typedef T value_type; + typedef integral_constant<T, Value> type; + +#if !defined(BOOST_NO_CXX11_CONSTEXPR) + constexpr operator value_type() const { + return Value; + } + + static constexpr T value = Value; +#else + enum { + value = Value + }; +#endif + }; +#endif + } + } +} + +#endif
diff --git a/boost/boost/align/detail/is_aligned.hpp b/boost/boost/align/detail/is_aligned.hpp new file mode 100644 index 0000000..41fb805 --- /dev/null +++ b/boost/boost/align/detail/is_aligned.hpp
@@ -0,0 +1,29 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNED_HPP +#define BOOST_ALIGN_DETAIL_IS_ALIGNED_HPP + +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/align/detail/address.hpp> +#include <boost/align/detail/is_alignment.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + inline bool is_aligned(std::size_t alignment, + const void* ptr) BOOST_NOEXCEPT + { + BOOST_ASSERT(detail::is_alignment(alignment)); + return (detail::address_t(ptr) & (alignment - 1)) == 0; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/is_alignment.hpp b/boost/boost/align/detail/is_alignment.hpp new file mode 100644 index 0000000..5321983 --- /dev/null +++ b/boost/boost/align/detail/is_alignment.hpp
@@ -0,0 +1,27 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP +#define BOOST_ALIGN_DETAIL_IS_ALIGNMENT_HPP + +#include <boost/config.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + namespace detail { + BOOST_CONSTEXPR inline bool is_alignment(std::size_t + value) BOOST_NOEXCEPT + { + return (value > 0) && ((value & (value - 1)) == 0); + } + } + } +} + +#endif
diff --git a/boost/boost/align/detail/is_alignment_constant.hpp b/boost/boost/align/detail/is_alignment_constant.hpp new file mode 100644 index 0000000..8f42260 --- /dev/null +++ b/boost/boost/align/detail/is_alignment_constant.hpp
@@ -0,0 +1,27 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_IS_ALIGNMENT_CONSTANT_HPP +#define BOOST_ALIGN_DETAIL_IS_ALIGNMENT_CONSTANT_HPP + +#include <boost/align/detail/integral_constant.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + namespace detail { + template<std::size_t N> + struct is_alignment_constant + : integral_constant<bool, + (N > 0) && ((N & (N - 1)) == 0)> { + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/max_align.hpp b/boost/boost/align/detail/max_align.hpp new file mode 100644 index 0000000..775121d --- /dev/null +++ b/boost/boost/align/detail/max_align.hpp
@@ -0,0 +1,27 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_MAX_ALIGN_HPP +#define BOOST_ALIGN_DETAIL_MAX_ALIGN_HPP + +#include <boost/align/detail/integral_constant.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + namespace detail { + template<std::size_t A, std::size_t B> + struct max_align + : integral_constant<std::size_t, + (A > B) ? A : B> { + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/max_count_of.hpp b/boost/boost/align/detail/max_count_of.hpp new file mode 100644 index 0000000..3ba4eae --- /dev/null +++ b/boost/boost/align/detail/max_count_of.hpp
@@ -0,0 +1,27 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_MAX_COUNT_OF_HPP +#define BOOST_ALIGN_DETAIL_MAX_COUNT_OF_HPP + +#include <boost/align/detail/integral_constant.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + namespace detail { + template<class T> + struct max_count_of + : integral_constant<std::size_t, + ~static_cast<std::size_t>(0) / sizeof(T)> { + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/min_size.hpp b/boost/boost/align/detail/min_size.hpp new file mode 100644 index 0000000..80d3a7a --- /dev/null +++ b/boost/boost/align/detail/min_size.hpp
@@ -0,0 +1,27 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_MIN_SIZE_HPP +#define BOOST_ALIGN_DETAIL_MIN_SIZE_HPP + +#include <boost/align/detail/integral_constant.hpp> +#include <cstddef> + +namespace boost { + namespace alignment { + namespace detail { + template<std::size_t A, std::size_t B> + struct min_size + : integral_constant<std::size_t, + (A < B) ? A : B> { + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/offset_object.hpp b/boost/boost/align/detail/offset_object.hpp new file mode 100644 index 0000000..8168595 --- /dev/null +++ b/boost/boost/align/detail/offset_object.hpp
@@ -0,0 +1,24 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_OFFSET_OBJECT_HPP +#define BOOST_ALIGN_DETAIL_OFFSET_OBJECT_HPP + +namespace boost { + namespace alignment { + namespace detail { + template<class T> + struct offset_object { + char offset; + T object; + }; + } + } +} + +#endif
diff --git a/boost/boost/align/detail/remove_traits.hpp b/boost/boost/align/detail/remove_traits.hpp new file mode 100644 index 0000000..d44860e --- /dev/null +++ b/boost/boost/align/detail/remove_traits.hpp
@@ -0,0 +1,90 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_DETAIL_REMOVE_TRAITS_HPP +#define BOOST_ALIGN_DETAIL_REMOVE_TRAITS_HPP + +#include <boost/config.hpp> + +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include <type_traits> +#else +#include <cstddef> +#endif + +namespace boost { + namespace alignment { + namespace detail { +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) + using std::remove_reference; + using std::remove_all_extents; + using std::remove_cv; +#else + template<class T> + struct remove_reference { + typedef T type; + }; + + template<class T> + struct remove_reference<T&> { + typedef T type; + }; + +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template<class T> + struct remove_reference<T&&> { + typedef T type; + }; +#endif + + template<class T> + struct remove_all_extents { + typedef T type; + }; + + template<class T> + struct remove_all_extents<T[]> { + typedef typename remove_all_extents<T>::type type; + }; + + template<class T, std::size_t N> + struct remove_all_extents<T[N]> { + typedef typename remove_all_extents<T>::type type; + }; + + template<class T> + struct remove_const { + typedef T type; + }; + + template<class T> + struct remove_const<const T> { + typedef T type; + }; + + template<class T> + struct remove_volatile { + typedef T type; + }; + + template<class T> + struct remove_volatile<volatile T> { + typedef T type; + }; + + template<class T> + struct remove_cv { + typedef typename remove_volatile<typename + remove_const<T>::type>::type type; + }; +#endif + } + } +} + +#endif
diff --git a/boost/boost/align/is_aligned.hpp b/boost/boost/align/is_aligned.hpp new file mode 100644 index 0000000..de28665 --- /dev/null +++ b/boost/boost/align/is_aligned.hpp
@@ -0,0 +1,14 @@ +/* + (c) 2014 Glen Joseph Fernandes + glenjofe at gmail dot com + + Distributed under the Boost Software + License, Version 1.0. + http://boost.org/LICENSE_1_0.txt +*/ +#ifndef BOOST_ALIGN_IS_ALIGNED_HPP +#define BOOST_ALIGN_IS_ALIGNED_HPP + +#include <boost/align/detail/is_aligned.hpp> + +#endif
diff --git a/boost/boost/aligned_storage.hpp b/boost/boost/aligned_storage.hpp new file mode 100644 index 0000000..b5455f0 --- /dev/null +++ b/boost/boost/aligned_storage.hpp
@@ -0,0 +1,143 @@ +//----------------------------------------------------------------------------- +// boost aligned_storage.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002-2003 +// Eric Friedman, Itay Maman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ALIGNED_STORAGE_HPP +#define BOOST_ALIGNED_STORAGE_HPP + +#include <cstddef> // for std::size_t + +#include "boost/config.hpp" +#include "boost/detail/workaround.hpp" +#include "boost/type_traits/alignment_of.hpp" +#include "boost/type_traits/type_with_alignment.hpp" +#include "boost/type_traits/is_pod.hpp" + +#include "boost/mpl/eval_if.hpp" +#include "boost/mpl/identity.hpp" + +#include "boost/type_traits/detail/bool_trait_def.hpp" + +namespace boost { + +namespace detail { namespace aligned_storage { + +BOOST_STATIC_CONSTANT( + std::size_t + , alignment_of_max_align = ::boost::alignment_of<max_align>::value + ); + +// +// To be TR1 conforming this must be a POD type: +// +template < + std::size_t size_ + , std::size_t alignment_ +> +struct aligned_storage_imp +{ + union data_t + { + char buf[size_]; + + typename ::boost::mpl::eval_if_c< + alignment_ == std::size_t(-1) + , ::boost::mpl::identity< ::boost::detail::max_align > + , ::boost::type_with_alignment<alignment_> + >::type align_; + } data_; + void* address() const { return const_cast<aligned_storage_imp*>(this); } +}; + +template< std::size_t alignment_ > +struct aligned_storage_imp<0u,alignment_> +{ + /* intentionally empty */ + void* address() const { return 0; } +}; + +}} // namespace detail::aligned_storage + +template < + std::size_t size_ + , std::size_t alignment_ = std::size_t(-1) +> +class aligned_storage : +#ifndef __BORLANDC__ + private +#else + public +#endif + ::boost::detail::aligned_storage::aligned_storage_imp<size_, alignment_> +{ + +public: // constants + + typedef ::boost::detail::aligned_storage::aligned_storage_imp<size_, alignment_> type; + + BOOST_STATIC_CONSTANT( + std::size_t + , size = size_ + ); + BOOST_STATIC_CONSTANT( + std::size_t + , alignment = ( + alignment_ == std::size_t(-1) + ? ::boost::detail::aligned_storage::alignment_of_max_align + : alignment_ + ) + ); + +private: // noncopyable + + aligned_storage(const aligned_storage&); + aligned_storage& operator=(const aligned_storage&); + +public: // structors + + aligned_storage() + { + } + + ~aligned_storage() + { + } + +public: // accessors + + void* address() + { + return static_cast<type*>(this)->address(); + } + + const void* address() const + { + return static_cast<const type*>(this)->address(); + } +}; + +// +// Make sure that is_pod recognises aligned_storage<>::type +// as a POD (Note that aligned_storage<> itself is not a POD): +// +template <std::size_t size_, std::size_t alignment_> +struct is_pod< ::boost::detail::aligned_storage::aligned_storage_imp<size_,alignment_> > + BOOST_TT_AUX_BOOL_C_BASE(true) +{ + BOOST_TT_AUX_BOOL_TRAIT_VALUE_DECL(true) +}; + + +} // namespace boost + +#include "boost/type_traits/detail/bool_trait_undef.hpp" + +#endif // BOOST_ALIGNED_STORAGE_HPP
diff --git a/boost/boost/any.hpp b/boost/boost/any.hpp new file mode 100644 index 0000000..437de2c --- /dev/null +++ b/boost/boost/any.hpp
@@ -0,0 +1,325 @@ +// See http://www.boost.org/libs/any for Documentation. + +#ifndef BOOST_ANY_INCLUDED +#define BOOST_ANY_INCLUDED + +#if defined(_MSC_VER) +# pragma once +#endif + +// what: variant type boost::any +// who: contributed by Kevlin Henney, +// with features contributed and bugs found by +// Antony Polukhin, Ed Brey, Mark Rodgers, +// Peter Dimov, and James Curran +// when: July 2001, April 2013 - May 2013 + +#include <algorithm> + +#include "boost/config.hpp" +#include <boost/type_index.hpp> +#include <boost/type_traits/remove_reference.hpp> +#include <boost/type_traits/decay.hpp> +#include <boost/type_traits/remove_cv.hpp> +#include <boost/type_traits/add_reference.hpp> +#include <boost/type_traits/is_reference.hpp> +#include <boost/type_traits/is_const.hpp> +#include <boost/throw_exception.hpp> +#include <boost/static_assert.hpp> +#include <boost/utility/enable_if.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_const.hpp> +#include <boost/mpl/if.hpp> + +namespace boost +{ + class any + { + public: // structors + + any() BOOST_NOEXCEPT + : content(0) + { + } + + template<typename ValueType> + any(const ValueType & value) + : content(new holder< + BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type + >(value)) + { + } + + any(const any & other) + : content(other.content ? other.content->clone() : 0) + { + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + // Move constructor + any(any&& other) BOOST_NOEXCEPT + : content(other.content) + { + other.content = 0; + } + + // Perfect forwarding of ValueType + template<typename ValueType> + any(ValueType&& value + , typename boost::disable_if<boost::is_same<any&, ValueType> >::type* = 0 // disable if value has type `any&` + , typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&` + : content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value))) + { + } +#endif + + ~any() BOOST_NOEXCEPT + { + delete content; + } + + public: // modifiers + + any & swap(any & rhs) BOOST_NOEXCEPT + { + std::swap(content, rhs.content); + return *this; + } + + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + template<typename ValueType> + any & operator=(const ValueType & rhs) + { + any(rhs).swap(*this); + return *this; + } + + any & operator=(any rhs) + { + any(rhs).swap(*this); + return *this; + } + +#else + any & operator=(const any& rhs) + { + any(rhs).swap(*this); + return *this; + } + + // move assignement + any & operator=(any&& rhs) BOOST_NOEXCEPT + { + rhs.swap(*this); + any().swap(rhs); + return *this; + } + + // Perfect forwarding of ValueType + template <class ValueType> + any & operator=(ValueType&& rhs) + { + any(static_cast<ValueType&&>(rhs)).swap(*this); + return *this; + } +#endif + + public: // queries + + bool empty() const BOOST_NOEXCEPT + { + return !content; + } + + void clear() BOOST_NOEXCEPT + { + any().swap(*this); + } + + const boost::typeindex::type_info& type() const BOOST_NOEXCEPT + { + return content ? content->type() : boost::typeindex::type_id<void>().type_info(); + } + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + private: // types +#else + public: // types (public so any_cast can be non-friend) +#endif + + class placeholder + { + public: // structors + + virtual ~placeholder() + { + } + + public: // queries + + virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT = 0; + + virtual placeholder * clone() const = 0; + + }; + + template<typename ValueType> + class holder : public placeholder + { + public: // structors + + holder(const ValueType & value) + : held(value) + { + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + holder(ValueType&& value) + : held(static_cast< ValueType&& >(value)) + { + } +#endif + public: // queries + + virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT + { + return boost::typeindex::type_id<ValueType>().type_info(); + } + + virtual placeholder * clone() const + { + return new holder(held); + } + + public: // representation + + ValueType held; + + private: // intentionally left unimplemented + holder & operator=(const holder &); + }; + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + + private: // representation + + template<typename ValueType> + friend ValueType * any_cast(any *) BOOST_NOEXCEPT; + + template<typename ValueType> + friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT; + +#else + + public: // representation (public so any_cast can be non-friend) + +#endif + + placeholder * content; + + }; + + inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + + class BOOST_SYMBOL_VISIBLE bad_any_cast : +#ifndef BOOST_NO_RTTI + public std::bad_cast +#else + public std::exception +#endif + { + public: + virtual const char * what() const BOOST_NOEXCEPT_OR_NOTHROW + { + return "boost::bad_any_cast: " + "failed conversion using boost::any_cast"; + } + }; + + template<typename ValueType> + ValueType * any_cast(any * operand) BOOST_NOEXCEPT + { + return operand && operand->type() == boost::typeindex::type_id<ValueType>() + ? &static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held + : 0; + } + + template<typename ValueType> + inline const ValueType * any_cast(const any * operand) BOOST_NOEXCEPT + { + return any_cast<ValueType>(const_cast<any *>(operand)); + } + + template<typename ValueType> + ValueType any_cast(any & operand) + { + typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; + + + nonref * result = any_cast<nonref>(&operand); + if(!result) + boost::throw_exception(bad_any_cast()); + + // Attempt to avoid construction of a temporary object in cases when + // `ValueType` is not a reference. Example: + // `static_cast<std::string>(*result);` + // which is equal to `std::string(*result);` + typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_< + boost::is_reference<ValueType>, + ValueType, + BOOST_DEDUCED_TYPENAME boost::add_reference<ValueType>::type + >::type ref_type; + + return static_cast<ref_type>(*result); + } + + template<typename ValueType> + inline ValueType any_cast(const any & operand) + { + typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; + return any_cast<const nonref &>(const_cast<any &>(operand)); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template<typename ValueType> + inline ValueType any_cast(any&& operand) + { + BOOST_STATIC_ASSERT_MSG( + boost::is_rvalue_reference<ValueType&&>::value /*true if ValueType is rvalue or just a value*/ + || boost::is_const< typename boost::remove_reference<ValueType>::type >::value, + "boost::any_cast shall not be used for getting nonconst references to temporary objects" + ); + return any_cast<ValueType>(operand); + } +#endif + + + // Note: The "unsafe" versions of any_cast are not part of the + // public interface and may be removed at any time. They are + // required where we know what type is stored in the any and can't + // use typeid() comparison, e.g., when our types may travel across + // different shared libraries. + template<typename ValueType> + inline ValueType * unsafe_any_cast(any * operand) BOOST_NOEXCEPT + { + return &static_cast<any::holder<ValueType> *>(operand->content)->held; + } + + template<typename ValueType> + inline const ValueType * unsafe_any_cast(const any * operand) BOOST_NOEXCEPT + { + return unsafe_any_cast<ValueType>(const_cast<any *>(operand)); + } +} + +// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#endif
diff --git a/boost/boost/archive/add_facet.hpp b/boost/boost/archive/add_facet.hpp new file mode 100644 index 0000000..242bdd9 --- /dev/null +++ b/boost/boost/archive/add_facet.hpp
@@ -0,0 +1,55 @@ +#ifndef BOOST_ARCHIVE_ADD_FACET_HPP +#define BOOST_ARCHIVE_ADD_FACET_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// add_facet.hpp + +// (C) Copyright 2003 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <locale> +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> + +// does STLport uses native STL for locales? +#if (defined(__SGI_STL_PORT)&& defined(_STLP_NO_OWN_IOSTREAMS)) +// and this native STL lib is old Dinkumware (has not defined _CPPLIB_VER) +# if (defined(_YVALS) && !defined(__IBMCPP__)) || !defined(_CPPLIB_VER) +# define BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT +# endif +#endif + +namespace boost { +namespace archive { + +template<class Facet> +inline std::locale * +add_facet(const std::locale &l, Facet * f){ + return + #if defined BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT + // std namespace used for native locale + new std::locale(std::_Addfac(l, f)); + #elif BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) // old Dinkumwar + // std namespace used for native locale + new std::locale(std::_Addfac(l, f)); + #else + // standard compatible + new std::locale(l, f); + #endif +} + +} // namespace archive +} // namespace boost + +#undef BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT + +#endif // BOOST_ARCHIVE_ADD_FACET_HPP
diff --git a/boost/boost/archive/archive_exception.hpp b/boost/boost/archive/archive_exception.hpp new file mode 100644 index 0000000..ffb430c --- /dev/null +++ b/boost/boost/archive/archive_exception.hpp
@@ -0,0 +1,99 @@ +#ifndef BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP +#define BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// archive/archive_exception.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <exception> +#include <boost/assert.hpp> +#include <string> + +#include <boost/config.hpp> +#include <boost/preprocessor/empty.hpp> +#include <boost/archive/detail/decl.hpp> + +// note: the only reason this is in here is that windows header +// includes #define exception_code _exception_code (arrrgghhhh!). +// the most expedient way to address this is be sure that this +// header is always included whenever this header file is included. +#if defined(BOOST_WINDOWS) +#include <excpt.h> +#endif + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by archives +// +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 + other_exception, // any excepton not listed below + unregistered_class, // attempt to serialize a pointer of + // an unregistered class + invalid_signature, // first line of archive does not contain + // expected string + unsupported_version,// archive created with library version + // subsequent to this one + pointer_conflict, // an attempt has been made to directly + // serialize an object which has + // already been serialized through a pointer. + // Were this permitted, the archive load would result + // in the creation of an extra copy of the obect. + incompatible_native_format, // attempt to read native binary format + // on incompatible platform + array_size_too_short,// array being loaded doesn't fit in array allocated + input_stream_error, // error on input stream + invalid_class_name, // class name greater than the maximum permitted. + // most likely a corrupted archive or an attempt + // to insert virus via buffer overrun method. + unregistered_cast, // base - derived relationship not registered with + // void_cast_register + unsupported_class_version, // type saved with a version # greater than the + // one used by the program. This indicates that the program + // needs to be rebuilt. + multiple_code_instantiation, // code for implementing serialization for some + // type has been instantiated in more than one module. + output_stream_error // error on input stream + } exception_code; +public: + exception_code code; + archive_exception( + exception_code c, + const char * e1 = NULL, + const char * e2 = NULL + ); + virtual ~archive_exception() throw(); + virtual const char *what() const throw(); +protected: + unsigned int + append(unsigned int l, const char * a); + archive_exception(); +}; + +}// namespace archive +}// namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif //BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP
diff --git a/boost/boost/archive/basic_archive.hpp b/boost/boost/archive/basic_archive.hpp new file mode 100644 index 0000000..0412112 --- /dev/null +++ b/boost/boost/archive/basic_archive.hpp
@@ -0,0 +1,304 @@ +#ifndef BOOST_ARCHIVE_BASIC_ARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_ARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_archive.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. +#include <cstring> // count +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/cstdint.hpp> // size_t +#include <boost/noncopyable.hpp> +#include <boost/integer_traits.hpp> + +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { + +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4244 4267 ) +#endif + +/* NOTE : Warning : Warning : Warning : Warning : Warning + * Don't ever changes this. If you do, they previously created + * binary archives won't be readable !!! + */ +class library_version_type { +private: + typedef uint_least16_t base_type; + base_type t; +public: + library_version_type(): t(0) {}; + explicit library_version_type(const unsigned int & t_) : t(t_){ + BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max); + } + library_version_type(const library_version_type & t_) : + t(t_.t) + {} + library_version_type & operator=(const library_version_type & rhs){ + t = rhs.t; + return *this; + } + // used for text output + operator base_type () const { + return t; + } + // used for text input + operator base_type & (){ + return t; + } + bool operator==(const library_version_type & rhs) const { + return t == rhs.t; + } + bool operator<(const library_version_type & rhs) const { + return t < rhs.t; + } +}; + +BOOST_ARCHIVE_DECL(library_version_type) +BOOST_ARCHIVE_VERSION(); + +class version_type { +private: + typedef uint_least32_t base_type; + base_type t; +public: + // should be private - but MPI fails if it's not!!! + version_type(): t(0) {}; + explicit version_type(const unsigned int & t_) : t(t_){ + BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max); + } + version_type(const version_type & t_) : + t(t_.t) + {} + version_type & operator=(const version_type & rhs){ + t = rhs.t; + return *this; + } + // used for text output + operator base_type () const { + return t; + } + // used for text intput + operator base_type & (){ + return t; + } + bool operator==(const version_type & rhs) const { + return t == rhs.t; + } + bool operator<(const version_type & rhs) const { + return t < rhs.t; + } +}; + +class class_id_type { +private: + typedef int_least16_t base_type; + base_type t; +public: + // should be private - but then can't use BOOST_STRONG_TYPE below + class_id_type() : t(0) {}; + explicit class_id_type(const int t_) : t(t_){ + BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max); + } + explicit class_id_type(const std::size_t t_) : t(t_){ + // BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max); + } + class_id_type(const class_id_type & t_) : + t(t_.t) + {} + class_id_type & operator=(const class_id_type & rhs){ + t = rhs.t; + return *this; + } + + // used for text output + operator int () const { + return t; + } + // used for text input + operator int_least16_t &() { + return t; + } + bool operator==(const class_id_type & rhs) const { + return t == rhs.t; + } + bool operator<(const class_id_type & rhs) const { + return t < rhs.t; + } +}; + +#define NULL_POINTER_TAG boost::archive::class_id_type(-1) + +class object_id_type { +private: + typedef uint_least32_t base_type; + base_type t; +public: + object_id_type(): t(0) {}; + // 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_) : + t(t_.t) + {} + object_id_type & operator=(const object_id_type & rhs){ + t = rhs.t; + return *this; + } + // used for text output + operator uint_least32_t () const { + return t; + } + // used for text input + operator uint_least32_t & () { + return t; + } + bool operator==(const object_id_type & rhs) const { + return t == rhs.t; + } + bool operator<(const object_id_type & rhs) const { + return t < rhs.t; + } +}; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + +struct tracking_type { + bool t; + explicit tracking_type(const bool t_ = false) + : t(t_) + {}; + tracking_type(const tracking_type & t_) + : t(t_.t) + {} + operator bool () const { + return t; + }; + operator bool & () { + return t; + }; + tracking_type & operator=(const bool t_){ + t = t_; + return *this; + } + bool operator==(const tracking_type & rhs) const { + return t == rhs.t; + } + bool operator==(const bool & rhs) const { + return t == rhs; + } + tracking_type & operator=(const tracking_type & rhs){ + t = rhs.t; + return *this; + } +}; + +struct class_name_type : + private boost::noncopyable +{ + char *t; + operator const char * & () const { + return const_cast<const char * &>(t); + } + operator char * () { + return t; + } + std::size_t size() const { + return std::strlen(t); + } + explicit class_name_type(const char *key_) + : t(const_cast<char *>(key_)){} + explicit class_name_type(char *key_) + : t(key_){} + class_name_type & operator=(const class_name_type & rhs){ + t = rhs.t; + return *this; + } +}; + +enum archive_flags { + no_header = 1, // suppress archive header info + no_codecvt = 2, // suppress alteration of codecvt facet + no_xml_tag_checking = 4, // suppress checking of xml tags + no_tracking = 8, // suppress ALL tracking + flags_last = 8 +}; + +BOOST_ARCHIVE_DECL(const char *) +BOOST_ARCHIVE_SIGNATURE(); + +/* NOTE : Warning : Warning : Warning : Warning : Warning + * If any of these are changed to different sized types, + * binary_iarchive won't be able to read older archives + * unless you rev the library version and include conditional + * code based on the library version. There is nothing + * inherently wrong in doing this - but you have to be super + * careful because it's easy to get wrong and start breaking + * old archives !!! + */ + +#define BOOST_ARCHIVE_STRONG_TYPEDEF(T, D) \ + class D : public T { \ + public: \ + explicit D(const T tt) : T(tt){} \ + }; \ +/**/ + +BOOST_ARCHIVE_STRONG_TYPEDEF(class_id_type, class_id_reference_type) +BOOST_ARCHIVE_STRONG_TYPEDEF(class_id_type, class_id_optional_type) +BOOST_ARCHIVE_STRONG_TYPEDEF(object_id_type, object_reference_type) + +}// namespace archive +}// namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#include <boost/serialization/level.hpp> + +// set implementation level to primitive for all types +// used internally by the serialization library + +BOOST_CLASS_IMPLEMENTATION(boost::archive::library_version_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::version_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::class_id_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::class_id_reference_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::class_id_optional_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::class_name_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::object_id_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::object_reference_type, primitive_type) +BOOST_CLASS_IMPLEMENTATION(boost::archive::tracking_type, primitive_type) + +#include <boost/serialization/is_bitwise_serializable.hpp> + +// set types used internally by the serialization library +// to be bitwise serializable + +BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::library_version_type) +BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::version_type) +BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::class_id_type) +BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::class_id_reference_type) +BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::class_id_optional_type) +BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::class_name_type) +BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::object_id_type) +BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::object_reference_type) +BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::tracking_type) + +#endif //BOOST_ARCHIVE_BASIC_ARCHIVE_HPP
diff --git a/boost/boost/archive/basic_binary_iarchive.hpp b/boost/boost/archive/basic_binary_iarchive.hpp new file mode 100644 index 0000000..a649d5e --- /dev/null +++ b/boost/boost/archive/basic_binary_iarchive.hpp
@@ -0,0 +1,228 @@ +#ifndef BOOST_ARCHIVE_BASIC_BINARY_IARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_BINARY_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_iarchive.hpp +// +// archives stored as native binary - this should be the fastest way +// to archive the state of a group of obects. It makes no attempt to +// convert to any canonical form. + +// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE +// ON PLATFORM APART FROM THE ONE THEY ARE CREATED ON + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/serialization/pfto.hpp> + +#include <boost/archive/basic_archive.hpp> +#include <boost/archive/detail/common_iarchive.hpp> +#include <boost/serialization/collection_size_type.hpp> +#include <boost/serialization/string.hpp> +#include <boost/serialization/item_version_type.hpp> +#include <boost/integer_traits.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_iarchive; +} // namespace detail + +///////////////////////////////////////////////////////////////////////// +// class basic_binary_iarchive - read serialized objects from a input binary stream +template<class Archive> +class basic_binary_iarchive : + public detail::common_iarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive<Archive>; + #else + friend class detail::interface_iarchive<Archive>; + #endif +#endif + // intermediate level to support override of operators + // fot templates in the absence of partial function + // template ordering. If we get here pass to base class + // note extra nonsense to sneak it pass the borland compiers + typedef detail::common_iarchive<Archive> detail_common_iarchive; + template<class T> + void load_override(T & t, BOOST_PFTO int version){ + this->detail_common_iarchive::load_override(t, static_cast<int>(version)); + } + + // include these to trap a change in binary format which + // isn't specifically handled + // upto 32K classes + BOOST_STATIC_ASSERT(sizeof(class_id_type) == sizeof(int_least16_t)); + BOOST_STATIC_ASSERT(sizeof(class_id_reference_type) == sizeof(int_least16_t)); + // upto 2G objects + BOOST_STATIC_ASSERT(sizeof(object_id_type) == sizeof(uint_least32_t)); + BOOST_STATIC_ASSERT(sizeof(object_reference_type) == sizeof(uint_least32_t)); + + // binary files don't include the optional information + void load_override(class_id_optional_type & /* t */, int){} + + void load_override(tracking_type & t, int /*version*/){ + library_version_type lvt = this->get_library_version(); + if(boost::archive::library_version_type(6) < lvt){ + int_least8_t x=0; + * this->This() >> x; + t = boost::archive::tracking_type(x); + } + else{ + bool x=0; + * this->This() >> x; + t = boost::archive::tracking_type(x); + } + } + void load_override(class_id_type & t, int version){ + library_version_type lvt = this->get_library_version(); + if(boost::archive::library_version_type(7) < lvt){ + this->detail_common_iarchive::load_override(t, version); + } + else + if(boost::archive::library_version_type(6) < lvt){ + int_least16_t x=0; + * this->This() >> x; + t = boost::archive::class_id_type(x); + } + else{ + int x=0; + * this->This() >> x; + t = boost::archive::class_id_type(x); + } + } + void load_override(class_id_reference_type & t, int version){ + load_override(static_cast<class_id_type &>(t), version); + } +#if 0 + void load_override(class_id_reference_type & t, int version){ + library_version_type lvt = this->get_library_version(); + if(boost::archive::library_version_type(7) < lvt){ + this->detail_common_iarchive::load_override(t, version); + } + else + if(boost::archive::library_version_type(6) < lvt){ + int_least16_t x=0; + * this->This() >> x; + t = boost::archive::class_id_reference_type( + boost::archive::class_id_type(x) + ); + } + else{ + int x=0; + * this->This() >> x; + t = boost::archive::class_id_reference_type( + boost::archive::class_id_type(x) + ); + } + } +#endif + + void load_override(version_type & t, int version){ + library_version_type lvt = this->get_library_version(); + if(boost::archive::library_version_type(7) < lvt){ + this->detail_common_iarchive::load_override(t, version); + } + else + if(boost::archive::library_version_type(6) < lvt){ + uint_least8_t x=0; + * this->This() >> x; + t = boost::archive::version_type(x); + } + else + if(boost::archive::library_version_type(5) < lvt){ + uint_least16_t x=0; + * this->This() >> x; + t = boost::archive::version_type(x); + } + else + if(boost::archive::library_version_type(2) < lvt){ + // upto 255 versions + unsigned char x=0; + * this->This() >> x; + t = version_type(x); + } + else{ + unsigned int x=0; + * this->This() >> x; + t = boost::archive::version_type(x); + } + } + + void load_override(boost::serialization::item_version_type & t, int version){ + library_version_type lvt = this->get_library_version(); +// if(boost::archive::library_version_type(7) < lvt){ + if(boost::archive::library_version_type(6) < lvt){ + this->detail_common_iarchive::load_override(t, version); + } + else + if(boost::archive::library_version_type(6) < lvt){ + uint_least16_t x=0; + * this->This() >> x; + t = boost::serialization::item_version_type(x); + } + else{ + unsigned int x=0; + * this->This() >> x; + t = boost::serialization::item_version_type(x); + } + } + + void load_override(serialization::collection_size_type & t, int version){ + if(boost::archive::library_version_type(5) < this->get_library_version()){ + this->detail_common_iarchive::load_override(t, version); + } + else{ + unsigned int x=0; + * this->This() >> x; + t = serialization::collection_size_type(x); + } + } + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(class_name_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + + basic_binary_iarchive(unsigned int flags) : + detail::common_iarchive<Archive>(flags) + {} +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_BINARY_IARCHIVE_HPP
diff --git a/boost/boost/archive/basic_binary_iprimitive.hpp b/boost/boost/archive/basic_binary_iprimitive.hpp new file mode 100644 index 0000000..4b41991 --- /dev/null +++ b/boost/boost/archive/basic_binary_iprimitive.hpp
@@ -0,0 +1,195 @@ +#ifndef BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP +#define BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +#if defined(_MSC_VER) +#pragma warning( disable : 4800 ) +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_iprimitive.hpp +// +// archives stored as native binary - this should be the fastest way +// to archive the state of a group of obects. It makes no attempt to +// convert to any canonical form. + +// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE +// ON PLATFORM APART FROM THE ONE THEY ARE CREATED ON + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <iosfwd> +#include <boost/assert.hpp> +#include <locale> +#include <cstring> // std::memcpy +#include <cstddef> // std::size_t +#include <streambuf> // basic_streambuf +#include <string> + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; + using ::size_t; +} // namespace std +#endif + +#include <boost/cstdint.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/serialization/throw_exception.hpp> +#include <boost/integer.hpp> +#include <boost/integer_traits.hpp> + +#include <boost/mpl/placeholders.hpp> +#include <boost/serialization/is_bitwise_serializable.hpp> +#include <boost/serialization/array.hpp> + +#include <boost/archive/basic_streambuf_locale_saver.hpp> +#include <boost/archive/archive_exception.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { + +template<class Ch> +class codecvt_null; + +///////////////////////////////////////////////////////////////////////////// +// class binary_iarchive - read serialized objects from a input binary stream +template<class Archive, class Elem, class Tr> +class basic_binary_iprimitive +{ +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + friend class load_access; +protected: +#else +public: +#endif + std::basic_streambuf<Elem, Tr> & m_sb; + // return a pointer to the most derived class + Archive * This(){ + return static_cast<Archive *>(this); + } + + #ifndef BOOST_NO_STD_LOCALE + boost::scoped_ptr<codecvt_null<Elem> > codecvt_facet; + boost::scoped_ptr<std::locale> archive_locale; + basic_streambuf_locale_saver<Elem, Tr> locale_saver; + #endif + + // main template for serilization of primitive types + template<class T> + void load(T & t){ + load_binary(& t, sizeof(T)); + } + + ///////////////////////////////////////////////////////// + // fundamental types that need special treatment + + // trap usage of invalid uninitialized boolean + void load(bool & t){ + load_binary(& t, sizeof(t)); + int i = t; + BOOST_ASSERT(0 == i || 1 == i); + (void)i; // warning suppression for release builds. + } + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load(char * t); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load(wchar_t * t); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_binary_iprimitive( + std::basic_streambuf<Elem, Tr> & sb, + bool no_codecvt + ); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_binary_iprimitive(); +public: + // we provide an optimized load for all fundamental types + // typedef serialization::is_bitwise_serializable<mpl::_1> + // use_array_optimization; + struct use_array_optimization { + template <class T> + #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS) + struct apply { + typedef typename boost::serialization::is_bitwise_serializable< T >::type type; + }; + #else + struct apply : public boost::serialization::is_bitwise_serializable< T > {}; + #endif + }; + + // the optimized load_array dispatches to load_binary + template <class ValueType> + void load_array(serialization::array<ValueType>& a, unsigned int) + { + load_binary(a.address(),a.count()*sizeof(ValueType)); + } + + void + load_binary(void *address, std::size_t count); +}; + +template<class Archive, class Elem, class Tr> +inline void +basic_binary_iprimitive<Archive, Elem, Tr>::load_binary( + void *address, + std::size_t count +){ + // note: an optimizer should eliminate the following for char files + BOOST_ASSERT( + static_cast<std::streamsize>(count / sizeof(Elem)) + <= boost::integer_traits<std::streamsize>::const_max + ); + std::streamsize s = static_cast<std::streamsize>(count / sizeof(Elem)); + std::streamsize scount = m_sb.sgetn( + static_cast<Elem *>(address), + s + ); + if(scount != s) + boost::serialization::throw_exception( + archive_exception(archive_exception::input_stream_error) + ); + // note: an optimizer should eliminate the following for char files + BOOST_ASSERT(count % sizeof(Elem) <= boost::integer_traits<std::streamsize>::const_max); + s = static_cast<std::streamsize>(count % sizeof(Elem)); + if(0 < s){ +// if(is.fail()) +// boost::serialization::throw_exception( +// archive_exception(archive_exception::stream_error) +// ); + Elem t; + scount = m_sb.sgetn(& t, 1); + if(scount != 1) + boost::serialization::throw_exception( + archive_exception(archive_exception::input_stream_error) + ); + std::memcpy(static_cast<char*>(address) + (count - s), &t, static_cast<std::size_t>(s)); + } +} + +} // namespace archive +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pop pragmas + +#endif // BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP
diff --git a/boost/boost/archive/basic_binary_oarchive.hpp b/boost/boost/archive/basic_binary_oarchive.hpp new file mode 100644 index 0000000..f8b53e9 --- /dev/null +++ b/boost/boost/archive/basic_binary_oarchive.hpp
@@ -0,0 +1,186 @@ +#ifndef BOOST_ARCHIVE_BASIC_BINARY_OARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_BINARY_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as native binary - this should be the fastest way +// to archive the state of a group of obects. It makes no attempt to +// convert to any canonical form. + +// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE +// ON PLATFORM APART FROM THE ONE THEY ARE CREATE ON + +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/serialization/pfto.hpp> + +#include <boost/integer.hpp> +#include <boost/integer_traits.hpp> + +#include <boost/archive/detail/common_oarchive.hpp> +#include <boost/serialization/string.hpp> +#include <boost/serialization/collection_size_type.hpp> +#include <boost/serialization/item_version_type.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_oarchive; +} // namespace detail + +////////////////////////////////////////////////////////////////////// +// class basic_binary_oarchive - write serialized objects to a binary output stream +// note: this archive has no pretensions to portability. Archive format +// may vary across machine architectures and compilers. About the only +// guarentee is that an archive created with this code will be readable +// by a program built with the same tools for the same machne. This class +// does have the virtue of buiding the smalles archive in the minimum amount +// of time. So under some circumstances it may be he right choice. +template<class Archive> +class basic_binary_oarchive : + public archive::detail::common_oarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive<Archive>; + #else + friend class detail::interface_oarchive<Archive>; + #endif +#endif + // any datatype not specifed below will be handled by base class + typedef detail::common_oarchive<Archive> detail_common_oarchive; + template<class T> + void save_override(const T & t, BOOST_PFTO int version){ + this->detail_common_oarchive::save_override(t, static_cast<int>(version)); + } + + // include these to trap a change in binary format which + // isn't specifically handled + BOOST_STATIC_ASSERT(sizeof(tracking_type) == sizeof(bool)); + // upto 32K classes + BOOST_STATIC_ASSERT(sizeof(class_id_type) == sizeof(int_least16_t)); + BOOST_STATIC_ASSERT(sizeof(class_id_reference_type) == sizeof(int_least16_t)); + // upto 2G objects + BOOST_STATIC_ASSERT(sizeof(object_id_type) == sizeof(uint_least32_t)); + BOOST_STATIC_ASSERT(sizeof(object_reference_type) == sizeof(uint_least32_t)); + + // binary files don't include the optional information + void save_override(const class_id_optional_type & /* t */, int){} + + // enable this if we decide to support generation of previous versions + #if 0 + void save_override(const boost::archive::version_type & t, int version){ + library_version_type lvt = this->get_library_version(); + if(boost::archive::library_version_type(7) < lvt){ + this->detail_common_oarchive::save_override(t, version); + } + else + if(boost::archive::library_version_type(6) < lvt){ + const boost::uint_least16_t x = t; + * this->This() << x; + } + else{ + const unsigned int x = t; + * this->This() << x; + } + } + void save_override(const boost::serialization::item_version_type & t, int version){ + library_version_type lvt = this->get_library_version(); + if(boost::archive::library_version_type(7) < lvt){ + this->detail_common_oarchive::save_override(t, version); + } + else + if(boost::archive::library_version_type(6) < lvt){ + const boost::uint_least16_t x = t; + * this->This() << x; + } + else{ + const unsigned int x = t; + * this->This() << x; + } + } + + void save_override(class_id_type & t, int version){ + library_version_type lvt = this->get_library_version(); + if(boost::archive::library_version_type(7) < lvt){ + this->detail_common_oarchive::save_override(t, version); + } + else + if(boost::archive::library_version_type(6) < lvt){ + const boost::int_least16_t x = t; + * this->This() << x; + } + else{ + const int x = t; + * this->This() << x; + } + } + void save_override(class_id_reference_type & t, int version){ + save_override(static_cast<class_id_type &>(t), version); + } + + #endif + + // explicitly convert to char * to avoid compile ambiguities + void save_override(const class_name_type & t, int){ + const std::string s(t); + * this->This() << s; + } + + #if 0 + void save_override(const serialization::collection_size_type & t, int){ + if (get_library_version() < boost::archive::library_version_type(6)){ + unsigned int x=0; + * this->This() >> x; + t = serialization::collection_size_type(x); + } + else{ + * this->This() >> t; + } + } + #endif + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + + basic_binary_oarchive(unsigned int flags) : + detail::common_oarchive<Archive>(flags) + {} +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_BINARY_OARCHIVE_HPP
diff --git a/boost/boost/archive/basic_binary_oprimitive.hpp b/boost/boost/archive/basic_binary_oprimitive.hpp new file mode 100644 index 0000000..a79cd1d --- /dev/null +++ b/boost/boost/archive/basic_binary_oprimitive.hpp
@@ -0,0 +1,187 @@ +#ifndef BOOST_ARCHIVE_BASIC_BINARY_OPRIMITIVE_HPP +#define BOOST_ARCHIVE_BASIC_BINARY_OPRIMITIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_oprimitive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as native binary - this should be the fastest way +// to archive the state of a group of obects. It makes no attempt to +// convert to any canonical form. + +// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE +// ON PLATFORM APART FROM THE ONE THEY ARE CREATE ON + +#include <iosfwd> +#include <boost/assert.hpp> +#include <locale> +#include <streambuf> // basic_streambuf +#include <string> +#include <cstddef> // size_t + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/cstdint.hpp> +#include <boost/integer.hpp> +#include <boost/integer_traits.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/serialization/throw_exception.hpp> + +#include <boost/archive/basic_streambuf_locale_saver.hpp> +#include <boost/archive/archive_exception.hpp> +#include <boost/serialization/is_bitwise_serializable.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/serialization/array.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { + +template<class Ch> +class codecvt_null; + +///////////////////////////////////////////////////////////////////////// +// class basic_binary_oprimitive - binary output of prmitives + +template<class Archive, class Elem, class Tr> +class basic_binary_oprimitive { +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + friend class save_access; +protected: +#else +public: +#endif + std::basic_streambuf<Elem, Tr> & m_sb; + // return a pointer to the most derived class + Archive * This(){ + return static_cast<Archive *>(this); + } + #ifndef BOOST_NO_STD_LOCALE + boost::scoped_ptr<codecvt_null<Elem> > codecvt_facet; + boost::scoped_ptr<std::locale> archive_locale; + basic_streambuf_locale_saver<Elem, Tr> locale_saver; + #endif + // default saving of primitives. + template<class T> + void save(const T & t) + { + save_binary(& t, sizeof(T)); + } + + ///////////////////////////////////////////////////////// + // fundamental types that need special treatment + + // trap usage of invalid uninitialized boolean which would + // otherwise crash on load. + void save(const bool t){ + BOOST_ASSERT(0 == static_cast<int>(t) || 1 == static_cast<int>(t)); + save_binary(& t, sizeof(t)); + } + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save(const char * t); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save(const wchar_t * t); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_binary_oprimitive( + std::basic_streambuf<Elem, Tr> & sb, + bool no_codecvt + ); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_binary_oprimitive(); +public: + + // we provide an optimized save for all fundamental types + // typedef serialization::is_bitwise_serializable<mpl::_1> + // use_array_optimization; + // workaround without using mpl lambdas + struct use_array_optimization { + template <class T> + #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS) + struct apply { + typedef typename boost::serialization::is_bitwise_serializable< T >::type type; + }; + #else + struct apply : public boost::serialization::is_bitwise_serializable< T > {}; + #endif + }; + + + // the optimized save_array dispatches to save_binary + template <class ValueType> + void save_array(boost::serialization::array<ValueType> const& a, unsigned int) + { + save_binary(a.address(),a.count()*sizeof(ValueType)); + } + + void save_binary(const void *address, std::size_t count); +}; + +template<class Archive, class Elem, class Tr> +inline void +basic_binary_oprimitive<Archive, Elem, Tr>::save_binary( + const void *address, + std::size_t count +){ + //BOOST_ASSERT( + // static_cast<std::size_t>((std::numeric_limits<std::streamsize>::max)()) >= count + //); + // note: if the following assertions fail + // a likely cause is that the output stream is set to "text" + // mode where by cr characters recieve special treatment. + // be sure that the output stream is opened with ios::binary + //if(os.fail()) + // boost::serialization::throw_exception( + // archive_exception(archive_exception::output_stream_error) + // ); + // figure number of elements to output - round up + count = ( count + sizeof(Elem) - 1) + / sizeof(Elem); + BOOST_ASSERT(count <= std::size_t(boost::integer_traits<std::streamsize>::const_max)); + std::streamsize scount = m_sb.sputn( + static_cast<const Elem *>(address), + static_cast<std::streamsize>(count) + ); + if(count != static_cast<std::size_t>(scount)) + boost::serialization::throw_exception( + archive_exception(archive_exception::output_stream_error) + ); + //os.write( + // static_cast<const typename OStream::char_type *>(address), + // count + //); + //BOOST_ASSERT(os.good()); +} + +} //namespace boost +} //namespace archive + +#include <boost/archive/detail/abi_suffix.hpp> // pop pragmas + +#endif // BOOST_ARCHIVE_BASIC_BINARY_OPRIMITIVE_HPP
diff --git a/boost/boost/archive/basic_streambuf_locale_saver.hpp b/boost/boost/archive/basic_streambuf_locale_saver.hpp new file mode 100644 index 0000000..64c8e5d --- /dev/null +++ b/boost/boost/archive/basic_streambuf_locale_saver.hpp
@@ -0,0 +1,75 @@ +#ifndef BOOST_ARCHIVE_BASIC_STREAMBUF_LOCALE_SAVER_HPP +#define BOOST_ARCHIVE_BASIC_STREAMBUF_LOCALE_SAVER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_streambuf_locale_saver.hpp + +// (C) Copyright 2005 Robert Ramey - http://www.rrsd.com + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// note derived from boost/io/ios_state.hpp +// Copyright 2002, 2005 Daryle Walker. Use, modification, and distribution +// are subject to the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) + +// See <http://www.boost.org/libs/io/> for the library's home page. + +#ifndef BOOST_NO_STD_LOCALE + +#include <locale> // for std::locale +#include <streambuf> // for std::basic_streambuf + +#include <boost/config.hpp> +#include <boost/noncopyable.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost{ +namespace archive{ + +template < typename Ch, class Tr > +class basic_streambuf_locale_saver : + private boost::noncopyable +{ +public: + typedef ::std::basic_streambuf<Ch, Tr> state_type; + typedef ::std::locale aspect_type; + explicit basic_streambuf_locale_saver( state_type &s ) + : s_save_( s ), a_save_( s.getloc() ) + {} + explicit basic_streambuf_locale_saver( state_type &s, aspect_type const &a ) + : s_save_( s ), a_save_( s.pubimbue(a) ) + {} + ~basic_streambuf_locale_saver() + { this->restore(); } + void restore(){ + s_save_.pubsync(); + s_save_.pubimbue( a_save_ ); + } +private: + state_type & s_save_; + aspect_type const a_save_; +}; + +} // archive +} // boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_NO_STD_LOCALE +#endif // BOOST_ARCHIVE_BASIC_STREAMBUF_LOCALE_SAVER_HPP
diff --git a/boost/boost/archive/basic_text_iarchive.hpp b/boost/boost/archive/basic_text_iarchive.hpp new file mode 100644 index 0000000..0e78ff6 --- /dev/null +++ b/boost/boost/archive/basic_text_iarchive.hpp
@@ -0,0 +1,97 @@ +#ifndef BOOST_ARCHIVE_BASIC_TEXT_IARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_TEXT_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these ar templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// note the fact that on libraries without wide characters, ostream is +// is not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream<IStream::char_type> but rather +// use two template parameters + +#include <boost/config.hpp> +#include <boost/serialization/pfto.hpp> +#include <boost/detail/workaround.hpp> + +#include <boost/archive/detail/common_iarchive.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_iarchive; +} // namespace detail + +///////////////////////////////////////////////////////////////////////// +// class basic_text_iarchive - read serialized objects from a input text stream +template<class Archive> +class basic_text_iarchive : + public detail::common_iarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive<Archive>; + #else + friend class detail::interface_iarchive<Archive>; + #endif +#endif + // intermediate level to support override of operators + // fot templates in the absence of partial function + // template ordering + typedef detail::common_iarchive<Archive> detail_common_iarchive; + template<class T> + void load_override(T & t, BOOST_PFTO int){ + this->detail_common_iarchive::load_override(t, 0); + } + // text file don't include the optional information + void load_override(class_id_optional_type & /*t*/, int){} + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(class_name_type & t, int); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(void); + + basic_text_iarchive(unsigned int flags) : + detail::common_iarchive<Archive>(flags) + {} + ~basic_text_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_TEXT_IARCHIVE_HPP
diff --git a/boost/boost/archive/basic_text_iprimitive.hpp b/boost/boost/archive/basic_text_iprimitive.hpp new file mode 100644 index 0000000..dabc3c8 --- /dev/null +++ b/boost/boost/archive/basic_text_iprimitive.hpp
@@ -0,0 +1,137 @@ +#ifndef BOOST_ARCHIVE_BASIC_TEXT_IPRIMITIVE_HPP +#define BOOST_ARCHIVE_BASIC_TEXT_IPRIMITIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_iprimitive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these are templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// Note the fact that on libraries without wide characters, ostream is +// not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream<IStream::char_type> but rather +// use two template parameters + +#include <boost/assert.hpp> +#include <locale> +#include <cstddef> // size_t + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; + #if ! defined(BOOST_DINKUMWARE_STDLIB) && ! defined(__SGI_STL_PORT) + using ::locale; + #endif +} // namespace std +#endif + +#include <boost/detail/workaround.hpp> +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) +#include <boost/archive/dinkumware.hpp> +#endif + +#include <boost/limits.hpp> +#include <boost/io/ios_state.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/static_assert.hpp> + +#include <boost/serialization/throw_exception.hpp> +#include <boost/archive/archive_exception.hpp> +#include <boost/archive/basic_streambuf_locale_saver.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { + +///////////////////////////////////////////////////////////////////////// +// class basic_text_iarchive - load serialized objects from a input text stream +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4244 4267 ) +#endif + +template<class IStream> +class basic_text_iprimitive { +protected: + IStream &is; + io::ios_flags_saver flags_saver; + io::ios_precision_saver precision_saver; + + #ifndef BOOST_NO_STD_LOCALE + boost::scoped_ptr<std::locale> archive_locale; + basic_streambuf_locale_saver< + typename IStream::char_type, + typename IStream::traits_type + > locale_saver; + #endif + + template<class T> + void load(T & t) + { + if(is >> t) + return; + boost::serialization::throw_exception( + archive_exception(archive_exception::input_stream_error) + ); + } + + void load(char & t) + { + short int i; + load(i); + t = i; + } + void load(signed char & t) + { + short int i; + load(i); + t = i; + } + void load(unsigned char & t) + { + unsigned short int i; + load(i); + t = i; + } + + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + void load(wchar_t & t) + { + BOOST_STATIC_ASSERT(sizeof(wchar_t) <= sizeof(int)); + int i; + load(i); + t = i; + } + #endif + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_text_iprimitive(IStream &is, bool no_codecvt); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_text_iprimitive(); +public: + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_binary(void *address, std::size_t count); +}; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + +} // namespace archive +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pop pragmas + +#endif // BOOST_ARCHIVE_BASIC_TEXT_IPRIMITIVE_HPP
diff --git a/boost/boost/archive/basic_text_oarchive.hpp b/boost/boost/archive/basic_text_oarchive.hpp new file mode 100644 index 0000000..0c60a31 --- /dev/null +++ b/boost/boost/archive/basic_text_oarchive.hpp
@@ -0,0 +1,120 @@ +#ifndef BOOST_ARCHIVE_BASIC_TEXT_OARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_TEXT_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these ar templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// note the fact that on libraries without wide characters, ostream is +// is not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream<OStream::char_type> but rather +// use two template parameters + +#include <boost/config.hpp> +#include <boost/serialization/pfto.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/archive/detail/common_oarchive.hpp> +#include <boost/serialization/string.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_oarchive; +} // namespace detail + +///////////////////////////////////////////////////////////////////////// +// class basic_text_oarchive +template<class Archive> +class basic_text_oarchive : + public detail::common_oarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive<Archive>; + #else + friend class detail::interface_oarchive<Archive>; + #endif +#endif + + enum { + none, + eol, + space + } delimiter; + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + newtoken(); + + void newline(){ + delimiter = eol; + } + + // default processing - kick back to base class. Note the + // extra stuff to get it passed borland compilers + typedef detail::common_oarchive<Archive> detail_common_oarchive; + template<class T> + void save_override(T & t, BOOST_PFTO int){ + this->detail_common_oarchive::save_override(t, 0); + } + + // start new objects on a new line + void save_override(const object_id_type & t, int){ + this->This()->newline(); + this->detail_common_oarchive::save_override(t, 0); + } + + // text file don't include the optional information + void save_override(const class_id_optional_type & /* t */, int){} + + void save_override(const class_name_type & t, int){ + const std::string s(t); + * this->This() << s; + } + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + + basic_text_oarchive(unsigned int flags) : + detail::common_oarchive<Archive>(flags), + delimiter(none) + {} + ~basic_text_oarchive(){} +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_TEXT_OARCHIVE_HPP
diff --git a/boost/boost/archive/basic_text_oprimitive.hpp b/boost/boost/archive/basic_text_oprimitive.hpp new file mode 100644 index 0000000..3c4cb5b --- /dev/null +++ b/boost/boost/archive/basic_text_oprimitive.hpp
@@ -0,0 +1,204 @@ +#ifndef BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP +#define BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_oprimitive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// archives stored as text - note these ar templated on the basic +// stream templates to accommodate wide (and other?) kind of characters +// +// note the fact that on libraries without wide characters, ostream is +// is not a specialization of basic_ostream which in fact is not defined +// in such cases. So we can't use basic_ostream<OStream::char_type> but rather +// use two template parameters + +#include <iomanip> +#include <locale> +#include <boost/assert.hpp> +#include <cstddef> // size_t + +#include <boost/config.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/io/ios_state.hpp> + +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) +#include <boost/archive/dinkumware.hpp> +#endif + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; + #if ! defined(BOOST_DINKUMWARE_STDLIB) && ! defined(__SGI_STL_PORT) + using ::locale; + #endif +} // namespace std +#endif + +#include <boost/type_traits/is_floating_point.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/limits.hpp> +#include <boost/integer.hpp> +#include <boost/io/ios_state.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/serialization/throw_exception.hpp> +#include <boost/archive/archive_exception.hpp> +#include <boost/archive/basic_streambuf_locale_saver.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { + +///////////////////////////////////////////////////////////////////////// +// class basic_text_oprimitive - output of prmitives to stream +template<class OStream> +class basic_text_oprimitive +{ +protected: + OStream &os; + io::ios_flags_saver flags_saver; + io::ios_precision_saver precision_saver; + + #ifndef BOOST_NO_STD_LOCALE + boost::scoped_ptr<std::locale> archive_locale; + basic_streambuf_locale_saver< + typename OStream::char_type, + typename OStream::traits_type + > locale_saver; + #endif + + ///////////////////////////////////////////////////////// + // fundamental types that need special treatment + void save(const bool t){ + // trap usage of invalid uninitialized boolean which would + // otherwise crash on load. + BOOST_ASSERT(0 == static_cast<int>(t) || 1 == static_cast<int>(t)); + if(os.fail()) + boost::serialization::throw_exception( + archive_exception(archive_exception::output_stream_error) + ); + os << t; + } + void save(const signed char t) + { + save(static_cast<short int>(t)); + } + void save(const unsigned char t) + { + save(static_cast<short unsigned int>(t)); + } + void save(const char t) + { + save(static_cast<short int>(t)); + } + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + void save(const wchar_t t) + { + BOOST_STATIC_ASSERT(sizeof(wchar_t) <= sizeof(int)); + save(static_cast<int>(t)); + } + #endif + + ///////////////////////////////////////////////////////// + // saving of any types not listed above + + template<class T> + void save_impl(const T &t, boost::mpl::bool_<false> &){ + if(os.fail()) + boost::serialization::throw_exception( + archive_exception(archive_exception::output_stream_error) + ); + os << t; + } + + ///////////////////////////////////////////////////////// + // floating point types need even more special treatment + // the following determines whether the type T is some sort + // of floating point type. Note that we then assume that + // the stream << operator is defined on that type - if not + // we'll get a compile time error. This is meant to automatically + // support synthesized types which support floating point + // operations. Also it should handle compiler dependent types + // such long double. Due to John Maddock. + + template<class T> + struct is_float { + typedef typename mpl::bool_< + boost::is_floating_point<T>::value + || (std::numeric_limits<T>::is_specialized + && !std::numeric_limits<T>::is_integer + && !std::numeric_limits<T>::is_exact + && std::numeric_limits<T>::max_exponent) + >::type type; + }; + + template<class T> + void save_impl(const T &t, boost::mpl::bool_<true> &){ + // must be a user mistake - can't serialize un-initialized data + if(os.fail()) + boost::serialization::throw_exception( + archive_exception(archive_exception::output_stream_error) + ); + // The formulae for the number of decimla digits required is given in + // http://www2.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1822.pdf + // which is derived from Kahan's paper: + // www.eecs.berkeley.edu/~wkahan/ieee754status/ieee754.ps + // const unsigned int digits = (std::numeric_limits<T>::digits * 3010) / 10000; + // note: I've commented out the above because I didn't get good results. e.g. + // in one case I got a difference of 19 units. + #ifndef BOOST_NO_CXX11_NUMERIC_LIMITS + const unsigned int digits = std::numeric_limits<T>::max_digits10; + #else + const unsigned int digits = std::numeric_limits<T>::digits10 + 2; + #endif + os << std::setprecision(digits) << std::scientific << t; + } + + template<class T> + void save(const T & t){ + boost::io::ios_flags_saver fs(os); + boost::io::ios_precision_saver ps(os); + typename is_float<T>::type tf; + save_impl(t, tf); + } + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_text_oprimitive(OStream & os, bool no_codecvt); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_text_oprimitive(); +public: + // unformatted append of one character + void put(typename OStream::char_type c){ + if(os.fail()) + boost::serialization::throw_exception( + archive_exception(archive_exception::output_stream_error) + ); + os.put(c); + } + // unformatted append of null terminated string + void put(const char * s){ + while('\0' != *s) + os.put(*s++); + } + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_binary(const void *address, std::size_t count); +}; + +} //namespace boost +} //namespace archive + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP
diff --git a/boost/boost/archive/basic_xml_archive.hpp b/boost/boost/archive/basic_xml_archive.hpp new file mode 100644 index 0000000..a4ad3a2 --- /dev/null +++ b/boost/boost/archive/basic_xml_archive.hpp
@@ -0,0 +1,67 @@ +#ifndef BOOST_ARCHIVE_BASIC_XML_TEXT_ARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_XML_TEXT_ARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_archive.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/archive/archive_exception.hpp> + +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { + +// constant strings used in xml i/o + +extern +BOOST_ARCHIVE_DECL(const char *) +BOOST_ARCHIVE_XML_OBJECT_ID(); + +extern +BOOST_ARCHIVE_DECL(const char *) +BOOST_ARCHIVE_XML_OBJECT_REFERENCE(); + +extern +BOOST_ARCHIVE_DECL(const char *) +BOOST_ARCHIVE_XML_CLASS_ID(); + +extern +BOOST_ARCHIVE_DECL(const char *) +BOOST_ARCHIVE_XML_CLASS_ID_REFERENCE(); + +extern +BOOST_ARCHIVE_DECL(const char *) +BOOST_ARCHIVE_XML_CLASS_NAME(); + +extern +BOOST_ARCHIVE_DECL(const char *) +BOOST_ARCHIVE_XML_TRACKING(); + +extern +BOOST_ARCHIVE_DECL(const char *) +BOOST_ARCHIVE_XML_VERSION(); + +extern +BOOST_ARCHIVE_DECL(const char *) +BOOST_ARCHIVE_XML_SIGNATURE(); + +}// namespace archive +}// namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_XML_TEXT_ARCHIVE_HPP +
diff --git a/boost/boost/archive/basic_xml_iarchive.hpp b/boost/boost/archive/basic_xml_iarchive.hpp new file mode 100644 index 0000000..5047fef --- /dev/null +++ b/boost/boost/archive/basic_xml_iarchive.hpp
@@ -0,0 +1,133 @@ +#ifndef BOOST_ARCHIVE_BASIC_XML_IARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_XML_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <boost/serialization/pfto.hpp> +#include <boost/detail/workaround.hpp> + +#include <boost/archive/detail/common_iarchive.hpp> + +#include <boost/serialization/nvp.hpp> +#include <boost/serialization/string.hpp> + +#include <boost/mpl/assert.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_iarchive; +} // namespace detail + +///////////////////////////////////////////////////////////////////////// +// class xml_iarchive - read serialized objects from a input text stream +template<class Archive> +class basic_xml_iarchive : + public detail::common_iarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive<Archive>; + #else + friend class detail::interface_iarchive<Archive>; + #endif +#endif + unsigned int depth; + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_start(const char *name); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_end(const char *name); + + // Anything not an attribute and not a name-value pair is an + // should be trapped here. + template<class T> + void load_override(T & t, BOOST_PFTO int) + { + // If your program fails to compile here, its most likely due to + // not specifying an nvp wrapper around the variable to + // be serialized. + BOOST_MPL_ASSERT((serialization::is_wrapper< T >)); + this->detail_common_iarchive::load_override(t, 0); + } + + // Anything not an attribute - see below - should be a name value + // pair and be processed here + typedef detail::common_iarchive<Archive> detail_common_iarchive; + template<class T> + void load_override( + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + const + #endif + boost::serialization::nvp< T > & t, + int + ){ + this->This()->load_start(t.name()); + this->detail_common_iarchive::load_override(t.value(), 0); + this->This()->load_end(t.name()); + } + + // specific overrides for attributes - handle as + // primitives. These are not name-value pairs + // so they have to be intercepted here and passed on to load. + // although the class_id is included in the xml text file in order + // to make the file self describing, it isn't used when loading + // an xml archive. So we can skip it here. Note: we MUST override + // it otherwise it will be loaded as a normal primitive w/o tag and + // leaving the archive in an undetermined state + void load_override(class_id_optional_type & /* t */, int){} + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(object_id_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(version_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(class_id_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + load_override(tracking_type & t, int); + // class_name_type can't be handled here as it depends upon the + // char type used by the stream. So require the derived implementation + // handle this. + // void load_override(class_name_type & t, int); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_xml_iarchive(unsigned int flags); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_xml_iarchive(); +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_XML_IARCHIVE_HPP
diff --git a/boost/boost/archive/basic_xml_oarchive.hpp b/boost/boost/archive/basic_xml_oarchive.hpp new file mode 100644 index 0000000..8a039fa --- /dev/null +++ b/boost/boost/archive/basic_xml_oarchive.hpp
@@ -0,0 +1,152 @@ +#ifndef BOOST_ARCHIVE_BASIC_XML_OARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_XML_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/serialization/pfto.hpp> +#include <boost/detail/workaround.hpp> + +#include <boost/archive/detail/common_oarchive.hpp> + +#include <boost/serialization/nvp.hpp> +#include <boost/serialization/tracking.hpp> +#include <boost/serialization/string.hpp> + + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_oarchive; +} // namespace detail + +////////////////////////////////////////////////////////////////////// +// class basic_xml_oarchive - write serialized objects to a xml output stream +template<class Archive> +class basic_xml_oarchive : + public detail::common_oarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: +#endif +#if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive<Archive>; +#else + friend class detail::interface_oarchive<Archive>; +#endif + friend class save_access; + // special stuff for xml output + unsigned int depth; + bool indent_next; + bool pending_preamble; + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + indent(); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + init(); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + write_attribute( + const char *attribute_name, + int t, + const char *conjunction = "=\"" + ); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + write_attribute( + const char *attribute_name, + const char *key + ); + // helpers used below + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_start(const char *name); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_end(const char *name); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + end_preamble(); + + // Anything not an attribute and not a name-value pair is an + // error and should be trapped here. + template<class T> + void save_override(T & t, BOOST_PFTO int) + { + // If your program fails to compile here, its most likely due to + // not specifying an nvp wrapper around the variable to + // be serialized. + BOOST_MPL_ASSERT((serialization::is_wrapper< T >)); + this->detail_common_oarchive::save_override(t, 0); + } + + // special treatment for name-value pairs. + typedef detail::common_oarchive<Archive> detail_common_oarchive; + template<class T> + void save_override( + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + const + #endif + ::boost::serialization::nvp< T > & t, + int + ){ + this->This()->save_start(t.name()); + this->detail_common_oarchive::save_override(t.const_value(), 0); + this->This()->save_end(t.name()); + } + + // specific overrides for attributes - not name value pairs so we + // want to trap them before the above "fall through" + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const object_id_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const object_reference_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const version_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const class_id_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const class_id_optional_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const class_id_reference_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const class_name_type & t, int); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) + save_override(const tracking_type & t, int); + + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + basic_xml_oarchive(unsigned int flags); + BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~basic_xml_oarchive(); +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_XML_OARCHIVE_HPP
diff --git a/boost/boost/archive/binary_iarchive.hpp b/boost/boost/archive/binary_iarchive.hpp new file mode 100644 index 0000000..ce67cca --- /dev/null +++ b/boost/boost/archive/binary_iarchive.hpp
@@ -0,0 +1,64 @@ +#ifndef BOOST_ARCHIVE_BINARY_IARCHIVE_HPP +#define BOOST_ARCHIVE_BINARY_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <istream> +#include <boost/archive/binary_iarchive_impl.hpp> +#include <boost/archive/detail/register_archive.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from binary_iarchive_impl instead. This will +// preserve correct static polymorphism. +class binary_iarchive : + public binary_iarchive_impl< + boost::archive::binary_iarchive, + std::istream::char_type, + std::istream::traits_type + >{ +public: + binary_iarchive(std::istream & is, unsigned int flags = 0) : + binary_iarchive_impl< + binary_iarchive, std::istream::char_type, std::istream::traits_type + >(is, flags) + {} + binary_iarchive(std::streambuf & bsb, unsigned int flags = 0) : + binary_iarchive_impl< + binary_iarchive, std::istream::char_type, std::istream::traits_type + >(bsb, flags) + {} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_iarchive) +BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::archive::binary_iarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_ARCHIVE_BINARY_IARCHIVE_HPP
diff --git a/boost/boost/archive/binary_iarchive_impl.hpp b/boost/boost/archive/binary_iarchive_impl.hpp new file mode 100644 index 0000000..a9afe61 --- /dev/null +++ b/boost/boost/archive/binary_iarchive_impl.hpp
@@ -0,0 +1,108 @@ +#ifndef BOOST_ARCHIVE_BINARY_IARCHIVE_IMPL_HPP +#define BOOST_ARCHIVE_BINARY_IARCHIVE_IMPL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_iarchive_impl.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <istream> +#include <boost/serialization/pfto.hpp> +#include <boost/archive/basic_binary_iprimitive.hpp> +#include <boost/archive/basic_binary_iarchive.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_iarchive; +} // namespace detail + +template<class Archive, class Elem, class Tr> +class binary_iarchive_impl : + public basic_binary_iprimitive<Archive, Elem, Tr>, + public basic_binary_iarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive<Archive>; + friend basic_binary_iarchive<Archive>; + friend load_access; + #else + friend class detail::interface_iarchive<Archive>; + friend class basic_binary_iarchive<Archive>; + friend class load_access; + #endif +#endif + // note: the following should not needed - but one compiler (vc 7.1) + // fails to compile one test (test_shared_ptr) without it !!! + // make this protected so it can be called from a derived archive + template<class T> + void load_override(T & t, BOOST_PFTO int){ + this->basic_binary_iarchive<Archive>::load_override(t, 0L); + } + void init(unsigned int flags){ + if(0 != (flags & no_header)) + return; + #if ! defined(__MWERKS__) + this->basic_binary_iarchive<Archive>::init(); + this->basic_binary_iprimitive<Archive, Elem, Tr>::init(); + #else + basic_binary_iarchive<Archive>::init(); + basic_binary_iprimitive<Archive, Elem, Tr>::init(); + #endif + } + binary_iarchive_impl( + std::basic_streambuf<Elem, Tr> & bsb, + unsigned int flags + ) : + basic_binary_iprimitive<Archive, Elem, Tr>( + bsb, + 0 != (flags & no_codecvt) + ), + basic_binary_iarchive<Archive>(flags) + { + init(flags); + } + binary_iarchive_impl( + std::basic_istream<Elem, Tr> & is, + unsigned int flags + ) : + basic_binary_iprimitive<Archive, Elem, Tr>( + * is.rdbuf(), + 0 != (flags & no_codecvt) + ), + basic_binary_iarchive<Archive>(flags) + { + init(flags); + } +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_ARCHIVE_BINARY_IARCHIVE_IMPL_HPP
diff --git a/boost/boost/archive/binary_oarchive.hpp b/boost/boost/archive/binary_oarchive.hpp new file mode 100644 index 0000000..89a86da --- /dev/null +++ b/boost/boost/archive/binary_oarchive.hpp
@@ -0,0 +1,64 @@ +#ifndef BOOST_ARCHIVE_BINARY_OARCHIVE_HPP +#define BOOST_ARCHIVE_BINARY_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <ostream> +#include <boost/config.hpp> +#include <boost/archive/binary_oarchive_impl.hpp> +#include <boost/archive/detail/register_archive.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from binary_oarchive_impl instead. This will +// preserve correct static polymorphism. +class binary_oarchive : + public binary_oarchive_impl< + binary_oarchive, std::ostream::char_type, std::ostream::traits_type + > +{ +public: + binary_oarchive(std::ostream & os, unsigned int flags = 0) : + binary_oarchive_impl< + binary_oarchive, std::ostream::char_type, std::ostream::traits_type + >(os, flags) + {} + binary_oarchive(std::streambuf & bsb, unsigned int flags = 0) : + binary_oarchive_impl< + binary_oarchive, std::ostream::char_type, std::ostream::traits_type + >(bsb, flags) + {} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_oarchive) +BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::archive::binary_oarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_ARCHIVE_BINARY_OARCHIVE_HPP
diff --git a/boost/boost/archive/binary_oarchive_impl.hpp b/boost/boost/archive/binary_oarchive_impl.hpp new file mode 100644 index 0000000..a8c9733 --- /dev/null +++ b/boost/boost/archive/binary_oarchive_impl.hpp
@@ -0,0 +1,109 @@ +#ifndef BOOST_ARCHIVE_BINARY_OARCHIVE_IMPL_HPP +#define BOOST_ARCHIVE_BINARY_OARCHIVE_IMPL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_oarchive_impl.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <ostream> +#include <boost/config.hpp> +#include <boost/serialization/pfto.hpp> +#include <boost/archive/basic_binary_oprimitive.hpp> +#include <boost/archive/basic_binary_oarchive.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_oarchive; +} // namespace detail + +template<class Archive, class Elem, class Tr> +class binary_oarchive_impl : + public basic_binary_oprimitive<Archive, Elem, Tr>, + public basic_binary_oarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive<Archive>; + friend basic_binary_oarchive<Archive>; + friend save_access; + #else + friend class detail::interface_oarchive<Archive>; + friend class basic_binary_oarchive<Archive>; + friend class save_access; + #endif +#endif + // note: the following should not needed - but one compiler (vc 7.1) + // fails to compile one test (test_shared_ptr) without it !!! + // make this protected so it can be called from a derived archive + template<class T> + void save_override(T & t, BOOST_PFTO int){ + this->basic_binary_oarchive<Archive>::save_override(t, 0L); + } + void init(unsigned int flags) { + if(0 != (flags & no_header)) + return; + #if ! defined(__MWERKS__) + this->basic_binary_oarchive<Archive>::init(); + this->basic_binary_oprimitive<Archive, Elem, Tr>::init(); + #else + basic_binary_oarchive<Archive>::init(); + basic_binary_oprimitive<Archive, Elem, Tr>::init(); + #endif + } + binary_oarchive_impl( + std::basic_streambuf<Elem, Tr> & bsb, + unsigned int flags + ) : + basic_binary_oprimitive<Archive, Elem, Tr>( + bsb, + 0 != (flags & no_codecvt) + ), + basic_binary_oarchive<Archive>(flags) + { + init(flags); + } + binary_oarchive_impl( + std::basic_ostream<Elem, Tr> & os, + unsigned int flags + ) : + basic_binary_oprimitive<Archive, Elem, Tr>( + * os.rdbuf(), + 0 != (flags & no_codecvt) + ), + basic_binary_oarchive<Archive>(flags) + { + init(flags); + } +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_ARCHIVE_BINARY_OARCHIVE_IMPL_HPP
diff --git a/boost/boost/archive/binary_wiarchive.hpp b/boost/boost/archive/binary_wiarchive.hpp new file mode 100644 index 0000000..775d8f8 --- /dev/null +++ b/boost/boost/archive/binary_wiarchive.hpp
@@ -0,0 +1,56 @@ +#ifndef BOOST_ARCHIVE_BINARY_WIARCHIVE_HPP +#define BOOST_ARCHIVE_BINARY_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <istream> // wistream +#include <boost/archive/binary_iarchive_impl.hpp> +#include <boost/archive/detail/register_archive.hpp> + +namespace boost { +namespace archive { + +class binary_wiarchive : + public binary_iarchive_impl< + binary_wiarchive, std::wistream::char_type, std::wistream::traits_type + > +{ +public: + binary_wiarchive(std::wistream & is, unsigned int flags = 0) : + binary_iarchive_impl< + binary_wiarchive, std::wistream::char_type, std::wistream::traits_type + >(is, flags) + {} + binary_wiarchive(std::wstreambuf & bsb, unsigned int flags = 0) : + binary_iarchive_impl< + binary_wiarchive, std::wistream::char_type, std::wistream::traits_type + >(bsb, flags) + {} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_wiarchive) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_BINARY_WIARCHIVE_HPP
diff --git a/boost/boost/archive/binary_woarchive.hpp b/boost/boost/archive/binary_woarchive.hpp new file mode 100644 index 0000000..a8817d6 --- /dev/null +++ b/boost/boost/archive/binary_woarchive.hpp
@@ -0,0 +1,59 @@ +#ifndef BOOST_ARCHIVE_BINARY_WOARCHIVE_HPP +#define BOOST_ARCHIVE_BINARY_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_woarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <ostream> +#include <boost/archive/binary_oarchive_impl.hpp> +#include <boost/archive/detail/register_archive.hpp> + +namespace boost { +namespace archive { + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from binary_oarchive_impl instead. This will +// preserve correct static polymorphism. +class binary_woarchive : + public binary_oarchive_impl< + binary_woarchive, std::wostream::char_type, std::wostream::traits_type + > +{ +public: + binary_woarchive(std::wostream & os, unsigned int flags = 0) : + binary_oarchive_impl< + binary_woarchive, std::wostream::char_type, std::wostream::traits_type + >(os, flags) + {} + binary_woarchive(std::wstreambuf & bsb, unsigned int flags = 0) : + binary_oarchive_impl< + binary_woarchive, std::wostream::char_type, std::wostream::traits_type + >(bsb, flags) + {} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_woarchive) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_BINARY_WOARCHIVE_HPP
diff --git a/boost/boost/archive/codecvt_null.hpp b/boost/boost/archive/codecvt_null.hpp new file mode 100644 index 0000000..75387a9 --- /dev/null +++ b/boost/boost/archive/codecvt_null.hpp
@@ -0,0 +1,104 @@ +#ifndef BOOST_ARCHIVE_CODECVT_NULL_HPP +#define BOOST_ARCHIVE_CODECVT_NULL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// codecvt_null.hpp: + +// (C) Copyright 2004 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <locale> +#include <cstddef> // NULL, size_t +#include <cwchar> // for mbstate_t +#include <boost/config.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std { +// For STLport on WinCE, BOOST_NO_STDC_NAMESPACE can get defined if STLport is putting symbols in its own namespace. +// In the case of codecvt, however, this does not mean that codecvt is in the global namespace (it will be in STLport's namespace) +# if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) + using ::codecvt; +# endif + using ::mbstate_t; + using ::size_t; +} // namespace +#endif + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +template<class Ch> +class codecvt_null; + +template<> +class codecvt_null<char> : public std::codecvt<char, char, std::mbstate_t> +{ + virtual bool do_always_noconv() const throw() { + return true; + } +public: + explicit codecvt_null(std::size_t no_locale_manage = 0) : + std::codecvt<char, char, std::mbstate_t>(no_locale_manage) + {} +}; + +template<> +class codecvt_null<wchar_t> : public std::codecvt<wchar_t, char, std::mbstate_t> +{ + virtual BOOST_WARCHIVE_DECL(std::codecvt_base::result) + do_out( + std::mbstate_t & state, + const wchar_t * first1, + const wchar_t * last1, + const wchar_t * & next1, + char * first2, + char * last2, + char * & next2 + ) const; + virtual BOOST_WARCHIVE_DECL(std::codecvt_base::result) + do_in( + std::mbstate_t & state, + const char * first1, + const char * last1, + const char * & next1, + wchar_t * first2, + wchar_t * last2, + wchar_t * & next2 + ) const; + virtual int do_encoding( ) const throw( ){ + return sizeof(wchar_t) / sizeof(char); + } + virtual int do_max_length( ) const throw( ){ + return do_encoding(); + } +public: + explicit codecvt_null(std::size_t no_locale_manage = 0) : + std::codecvt<wchar_t, char, std::mbstate_t>(no_locale_manage) + {} +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif +#include <boost/archive/detail/abi_suffix.hpp> // pop pragmas + +#endif //BOOST_ARCHIVE_CODECVT_NULL_HPP
diff --git a/boost/boost/archive/detail/abi_prefix.hpp b/boost/boost/archive/detail/abi_prefix.hpp new file mode 100644 index 0000000..e39ef11 --- /dev/null +++ b/boost/boost/archive/detail/abi_prefix.hpp
@@ -0,0 +1,20 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// abi_prefix.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config/abi_prefix.hpp> // must be the last header +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4251 4231 4660 4275) +#endif + +#if defined( __BORLANDC__ ) +#pragma nopushoptwarn +#endif +
diff --git a/boost/boost/archive/detail/abi_suffix.hpp b/boost/boost/archive/detail/abi_suffix.hpp new file mode 100644 index 0000000..a283b36 --- /dev/null +++ b/boost/boost/archive/detail/abi_suffix.hpp
@@ -0,0 +1,19 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// abi_suffix.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif +#include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#if defined( __BORLANDC__ ) +#pragma nopushoptwarn +#endif +
diff --git a/boost/boost/archive/detail/archive_serializer_map.hpp b/boost/boost/archive/detail/archive_serializer_map.hpp new file mode 100644 index 0000000..53fcae4 --- /dev/null +++ b/boost/boost/archive/detail/archive_serializer_map.hpp
@@ -0,0 +1,55 @@ +#ifndef BOOST_ARCHIVE_SERIALIZER_MAP_HPP +#define BOOST_ARCHIVE_SERIALIZER_MAP_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// archive_serializer_map.hpp: extenstion of type_info required for +// serialization. + +// (C) Copyright 2009 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// note: this is nothing more than the thinest of wrappers around +// basic_serializer_map so we can have a one map / archive type. + +#include <boost/config.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +class basic_serializer; + +template<class Archive> +class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +archive_serializer_map { +public: + static bool insert(const basic_serializer * bs); + static void erase(const basic_serializer * bs); + static const basic_serializer * find( + const boost::serialization::extended_type_info & type_ + ); +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // must be the last header + +#endif //BOOST_ARCHIVE_SERIALIZER_MAP_HPP
diff --git a/boost/boost/archive/detail/auto_link_archive.hpp b/boost/boost/archive/detail/auto_link_archive.hpp new file mode 100644 index 0000000..79b0e49 --- /dev/null +++ b/boost/boost/archive/detail/auto_link_archive.hpp
@@ -0,0 +1,48 @@ +#ifndef BOOST_ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// auto_link_archive.hpp +// +// (c) Copyright Robert Ramey 2004 +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See library home page at http://www.boost.org/libs/serialization + +//----------------------------------------------------------------------------// + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +// enable automatic library variant selection ------------------------------// + +#include <boost/archive/detail/decl.hpp> + +#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_SERIALIZATION_NO_LIB) \ +&& !defined(BOOST_ARCHIVE_SOURCE) && !defined(BOOST_WARCHIVE_SOURCE) \ +&& !defined(BOOST_SERIALIZATION_SOURCE) + + // Set the name of our library, this will get undef'ed by auto_link.hpp + // once it's done with it: + // + #define BOOST_LIB_NAME boost_serialization + // + // If we're importing code from a dll, then tell auto_link.hpp about it: + // + #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK) + # define BOOST_DYN_LINK + #endif + // + // And include the header that does the work: + // + #include <boost/config/auto_link.hpp> +#endif // auto-linking disabled + +#endif // BOOST_ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP
diff --git a/boost/boost/archive/detail/auto_link_warchive.hpp b/boost/boost/archive/detail/auto_link_warchive.hpp new file mode 100644 index 0000000..683d191 --- /dev/null +++ b/boost/boost/archive/detail/auto_link_warchive.hpp
@@ -0,0 +1,47 @@ +#ifndef BOOST_ARCHIVE_DETAIL_AUTO_LINK_WARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_AUTO_LINK_WARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// auto_link_warchive.hpp +// +// (c) Copyright Robert Ramey 2004 +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See library home page at http://www.boost.org/libs/serialization + +//----------------------------------------------------------------------------// + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +// enable automatic library variant selection ------------------------------// + +#include <boost/archive/detail/decl.hpp> + +#if !defined(BOOST_WARCHIVE_SOURCE) \ +&& !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_SERIALIZATION_NO_LIB) + +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#define BOOST_LIB_NAME boost_wserialization +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK) +# define BOOST_DYN_LINK +#endif +// +// And include the header that does the work: +// +#include <boost/config/auto_link.hpp> +#endif // auto-linking disabled + +#endif // ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP
diff --git a/boost/boost/archive/detail/basic_archive_impl.hpp b/boost/boost/archive/detail/basic_archive_impl.hpp new file mode 100644 index 0000000..860066f --- /dev/null +++ b/boost/boost/archive/detail/basic_archive_impl.hpp
@@ -0,0 +1,45 @@ +#ifndef BOOST_ARCHIVE_DETAIL_BASIC_ARCHIVE_IMPL_HPP +#define BOOST_ARCHIVE_DETAIL_BASIC_ARCHIVE_IMPL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_archive_impl.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <set> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +////////////////////////////////////////////////////////////////////// +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_archive_impl +{ +}; + +} // namespace detail +} // namespace serialization +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif //BOOST_ARCHIVE_DETAIL_BASIC_ARCHIVE_IMPL_HPP + + +
diff --git a/boost/boost/archive/detail/basic_config.hpp b/boost/boost/archive/detail/basic_config.hpp new file mode 100644 index 0000000..4bd2723 --- /dev/null +++ b/boost/boost/archive/detail/basic_config.hpp
@@ -0,0 +1,45 @@ +#ifndef BOOST_ARCHIVE_DETAIL_BASIC_CONFIG_HPP +#define BOOST_ARCHIVE_DETAIL_BASIC_CONFIG_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +// basic_config.hpp ---------------------------------------------// + +// (c) Copyright Robert Ramey 2004 +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See library home page at http://www.boost.org/libs/serialization + +//----------------------------------------------------------------------------// + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +#include <boost/config.hpp> + +#ifdef BOOST_HAS_DECLSPEC // defined in config system +// we need to import/export our code only if the user has specifically +// asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost +// libraries to be dynamically linked, or BOOST_ARCHIVE_DYN_LINK +// if they want just this one to be dynamically linked: +#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_ARCHIVE_DYN_LINK) +// export if this is our own source, otherwise import: +#ifdef BOOST_ARCHIVE_SOURCE +# define BOOST_ARCHIVE_DECL __declspec(dllexport) +#else +# define BOOST_ARCHIVE_DECL __declspec(dllimport) +#endif // BOOST_ARCHIVE_SOURCE +#endif // DYN_LINK +#endif // BOOST_HAS_DECLSPEC +// +// if BOOST_ARCHIVE_DECL isn't defined yet define it now: +#ifndef BOOST_ARCHIVE_DECL +#define BOOST_ARCHIVE_DECL +#endif + +#endif // BOOST_ARCHIVE_DETAIL_BASIC_CONFIG_HPP
diff --git a/boost/boost/archive/detail/basic_iarchive.hpp b/boost/boost/archive/detail/basic_iarchive.hpp new file mode 100644 index 0000000..ce8dbc0 --- /dev/null +++ b/boost/boost/archive/detail/basic_iarchive.hpp
@@ -0,0 +1,103 @@ +#ifndef BOOST_ARCHIVE_DETAIL_BASIC_IARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_BASIC_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_iarchive.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// can't use this - much as I'd like to as borland doesn't support it + +#include <boost/config.hpp> +#include <boost/noncopyable.hpp> +#include <boost/scoped_ptr.hpp> + +#include <boost/serialization/tracking_enum.hpp> +#include <boost/archive/basic_archive.hpp> +#include <boost/archive/detail/decl.hpp> +#include <boost/archive/detail/helper_collection.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +class basic_iarchive_impl; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer; +////////////////////////////////////////////////////////////////////// +// class basic_iarchive - read serialized objects from a input stream +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive : + private boost::noncopyable, + public boost::archive::detail::helper_collection +{ + friend class basic_iarchive_impl; + // hide implementation of this class to minimize header conclusion + boost::scoped_ptr<basic_iarchive_impl> pimpl; + + virtual void vload(version_type &t) = 0; + virtual void vload(object_id_type &t) = 0; + virtual void vload(class_id_type &t) = 0; + virtual void vload(class_id_optional_type &t) = 0; + virtual void vload(class_name_type &t) = 0; + virtual void vload(tracking_type &t) = 0; +protected: + basic_iarchive(unsigned int flags); +public: + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_iarchive(); + // note: NOT part of the public API. + void next_object_pointer(void *t); + void register_basic_serializer( + const basic_iserializer & bis + ); + void load_object( + void *t, + const basic_iserializer & bis + ); + const basic_pointer_iserializer * + load_pointer( + void * & t, + const basic_pointer_iserializer * bpis_ptr, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & eti + ) + + ); + // real public API starts here + void + set_library_version(library_version_type archive_library_version); + library_version_type + get_library_version() const; + unsigned int + get_flags() const; + void + reset_object_address(const void * new_address, const void * old_address); + void + delete_created_pointers(); +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif //BOOST_ARCHIVE_DETAIL_BASIC_IARCHIVE_HPP
diff --git a/boost/boost/archive/detail/basic_iserializer.hpp b/boost/boost/archive/detail/basic_iserializer.hpp new file mode 100644 index 0000000..3bff3e1 --- /dev/null +++ b/boost/boost/archive/detail/basic_iserializer.hpp
@@ -0,0 +1,95 @@ +#ifndef BOOST_ARCHIVE_DETAIL_BASIC_ISERIALIZER_HPP +#define BOOST_ARCHIVE_DETAIL_BASIC_ISERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_iserializer.hpp: extenstion of type_info required for serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstdlib> // NULL +#include <boost/config.hpp> + +#include <boost/archive/basic_archive.hpp> +#include <boost/archive/detail/decl.hpp> +#include <boost/archive/detail/basic_serializer.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +// forward declarations +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer; + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer : + public basic_serializer +{ +private: + basic_pointer_iserializer *m_bpis; +protected: + explicit basic_iserializer( + const boost::serialization::extended_type_info & type + ); + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_iserializer(); +public: + bool serialized_as_pointer() const { + return m_bpis != NULL; + } + void set_bpis(basic_pointer_iserializer *bpis){ + m_bpis = bpis; + } + const basic_pointer_iserializer * get_bpis_ptr() const { + return m_bpis; + } + virtual void load_object_data( + basic_iarchive & ar, + void *x, + const unsigned int file_version + ) const = 0; + // returns true if class_info should be saved + virtual bool class_info() const = 0 ; + // returns true if objects should be tracked + virtual bool tracking(const unsigned int) const = 0 ; + // returns class version + virtual version_type version() const = 0 ; + // returns true if this class is polymorphic + virtual bool is_polymorphic() const = 0; + virtual void destroy(/*const*/ void *address) const = 0 ; +}; + +} // namespae detail +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_BASIC_ISERIALIZER_HPP
diff --git a/boost/boost/archive/detail/basic_oarchive.hpp b/boost/boost/archive/detail/basic_oarchive.hpp new file mode 100644 index 0000000..fe192f0 --- /dev/null +++ b/boost/boost/archive/detail/basic_oarchive.hpp
@@ -0,0 +1,96 @@ +#ifndef BOOST_ARCHIVE_BASIC_OARCHIVE_HPP +#define BOOST_ARCHIVE_BASIC_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_oarchive.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstddef> // NULL +#include <boost/config.hpp> +#include <boost/noncopyable.hpp> +#include <boost/scoped_ptr.hpp> + +#include <boost/archive/basic_archive.hpp> +#include <boost/serialization/tracking_enum.hpp> +#include <boost/archive/detail/helper_collection.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +class basic_oarchive_impl; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer; + +////////////////////////////////////////////////////////////////////// +// class basic_oarchive - write serialized objects to an output stream +class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive : + private boost::noncopyable, + public boost::archive::detail::helper_collection +{ + friend class basic_oarchive_impl; + // hide implementation of this class to minimize header conclusion + boost::scoped_ptr<basic_oarchive_impl> pimpl; + + // overload these to bracket object attributes. Used to implement + // xml archives + virtual void vsave(const version_type t) = 0; + virtual void vsave(const object_id_type t) = 0; + virtual void vsave(const object_reference_type t) = 0; + virtual void vsave(const class_id_type t) = 0; + virtual void vsave(const class_id_optional_type t) = 0; + virtual void vsave(const class_id_reference_type t) = 0; + virtual void vsave(const class_name_type & t) = 0; + virtual void vsave(const tracking_type t) = 0; +protected: + basic_oarchive(unsigned int flags = 0); + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_oarchive(); +public: + // note: NOT part of the public interface + void register_basic_serializer( + const basic_oserializer & bos + ); + void save_object( + const void *x, + const basic_oserializer & bos + ); + void save_pointer( + const void * t, + const basic_pointer_oserializer * bpos_ptr + ); + void save_null_pointer(){ + vsave(NULL_POINTER_TAG); + } + // real public interface starts here + void end_preamble(); // default implementation does nothing + library_version_type get_library_version() const; + unsigned int get_flags() const; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif //BOOST_ARCHIVE_BASIC_OARCHIVE_HPP
diff --git a/boost/boost/archive/detail/basic_oserializer.hpp b/boost/boost/archive/detail/basic_oserializer.hpp new file mode 100644 index 0000000..6ae063f --- /dev/null +++ b/boost/boost/archive/detail/basic_oserializer.hpp
@@ -0,0 +1,93 @@ +#ifndef BOOST_SERIALIZATION_BASIC_OSERIALIZER_HPP +#define BOOST_SERIALIZATION_BASIC_OSERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_oserializer.hpp: extenstion of type_info required for serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstddef> // NULL +#include <boost/config.hpp> +#include <boost/noncopyable.hpp> + +#include <boost/archive/basic_archive.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/basic_serializer.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +// forward declarations +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer; + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer : + public basic_serializer +{ +private: + basic_pointer_oserializer *m_bpos; +protected: + explicit basic_oserializer( + const boost::serialization::extended_type_info & type_ + ); + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_oserializer(); +public: + bool serialized_as_pointer() const { + return m_bpos != NULL; + } + void set_bpos(basic_pointer_oserializer *bpos){ + m_bpos = bpos; + } + const basic_pointer_oserializer * get_bpos() const { + return m_bpos; + } + virtual void save_object_data( + basic_oarchive & ar, const void * x + ) const = 0; + // returns true if class_info should be saved + virtual bool class_info() const = 0; + // returns true if objects should be tracked + virtual bool tracking(const unsigned int flags) const = 0; + // returns class version + virtual version_type version() const = 0; + // returns true if this class is polymorphic + virtual bool is_polymorphic() const = 0; +}; + +} // namespace detail +} // namespace serialization +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_SERIALIZATION_BASIC_OSERIALIZER_HPP
diff --git a/boost/boost/archive/detail/basic_pointer_iserializer.hpp b/boost/boost/archive/detail/basic_pointer_iserializer.hpp new file mode 100644 index 0000000..86badc1 --- /dev/null +++ b/boost/boost/archive/detail/basic_pointer_iserializer.hpp
@@ -0,0 +1,74 @@ +#ifndef BOOST_ARCHIVE_BASIC_POINTER_ISERIALIZER_HPP +#define BOOST_ARCHIVE_BASIC_POINTER_ISERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_pointer_oserializer.hpp: extenstion of type_info required for +// serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. +#include <boost/config.hpp> +#include <boost/noncopyable.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/basic_serializer.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +// forward declarations +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer; + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer + : public basic_serializer { +protected: + explicit basic_pointer_iserializer( + const boost::serialization::extended_type_info & type_ + ); + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_pointer_iserializer(); +public: + virtual void * heap_allocation() const = 0; + virtual const basic_iserializer & get_basic_serializer() const = 0; + virtual void load_object_ptr( + basic_iarchive & ar, + void * x, + const unsigned int file_version + ) const = 0; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_POINTER_ISERIALIZER_HPP
diff --git a/boost/boost/archive/detail/basic_pointer_oserializer.hpp b/boost/boost/archive/detail/basic_pointer_oserializer.hpp new file mode 100644 index 0000000..bafc46a --- /dev/null +++ b/boost/boost/archive/detail/basic_pointer_oserializer.hpp
@@ -0,0 +1,72 @@ +#ifndef BOOST_ARCHIVE_BASIC_POINTER_OSERIALIZER_HPP +#define BOOST_ARCHIVE_BASIC_POINTER_OSERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_pointer_oserializer.hpp: extenstion of type_info required for +// serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. +#include <boost/config.hpp> +#include <boost/noncopyable.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/basic_serializer.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer; + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer : + public basic_serializer +{ +protected: + explicit basic_pointer_oserializer( + const boost::serialization::extended_type_info & type_ + ); +public: + // account for bogus gcc warning + #if defined(__GNUC__) + virtual + #endif + ~basic_pointer_oserializer(); + virtual const basic_oserializer & get_basic_serializer() const = 0; + virtual void save_object_ptr( + basic_oarchive & ar, + const void * x + ) const = 0; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_BASIC_POINTER_OSERIALIZER_HPP
diff --git a/boost/boost/archive/detail/basic_serializer.hpp b/boost/boost/archive/detail/basic_serializer.hpp new file mode 100644 index 0000000..c7d3b4b --- /dev/null +++ b/boost/boost/archive/detail/basic_serializer.hpp
@@ -0,0 +1,79 @@ +#ifndef BOOST_ARCHIVE_BASIC_SERIALIZER_HPP +#define BOOST_ARCHIVE_BASIC_SERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_serializer.hpp: extenstion of type_info required for serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> +#include <cstddef> // NULL + +#include <boost/noncopyable.hpp> +#include <boost/config.hpp> +#include <boost/serialization/extended_type_info.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { +namespace detail { + +class basic_serializer : + private boost::noncopyable +{ + const boost::serialization::extended_type_info * m_eti; +protected: + explicit basic_serializer( + const boost::serialization::extended_type_info & eti + ) : + m_eti(& eti) + { + BOOST_ASSERT(NULL != & eti); + } +public: + inline bool + operator<(const basic_serializer & rhs) const { + // can't compare address since there can be multiple eti records + // for the same type in different execution modules (that is, DLLS) + // leave this here as a reminder not to do this! + // return & lhs.get_eti() < & rhs.get_eti(); + return get_eti() < rhs.get_eti(); + } + const char * get_debug_info() const { + return m_eti->get_debug_info(); + } + const boost::serialization::extended_type_info & get_eti() const { + return * m_eti; + } +}; + +class basic_serializer_arg : public basic_serializer { +public: + basic_serializer_arg(const serialization::extended_type_info & eti) : + basic_serializer(eti) + {} +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_ARCHIVE_BASIC_SERIALIZER_HPP
diff --git a/boost/boost/archive/detail/basic_serializer_map.hpp b/boost/boost/archive/detail/basic_serializer_map.hpp new file mode 100644 index 0000000..202c20e --- /dev/null +++ b/boost/boost/archive/detail/basic_serializer_map.hpp
@@ -0,0 +1,69 @@ +#ifndef BOOST_SERIALIZER_MAP_HPP +#define BOOST_SERIALIZER_MAP_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_serializer_map.hpp: extenstion of type_info required for serialization. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <set> + +#include <boost/config.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 + +namespace boost { +namespace serialization { + class extended_type_info; +} + +namespace archive { +namespace detail { + +class basic_serializer; + +class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_serializer_map : public + boost::noncopyable +{ + struct type_info_pointer_compare + { + bool operator()( + const basic_serializer * lhs, const basic_serializer * rhs + ) const ; + }; + typedef std::set< + const basic_serializer *, + type_info_pointer_compare + > map_type; + map_type m_map; +public: + bool insert(const basic_serializer * bs); + void erase(const basic_serializer * bs); + const basic_serializer * find( + const boost::serialization::extended_type_info & type_ + ) const; +private: + // cw 8.3 requires this + basic_serializer_map& operator=(basic_serializer_map const&); +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // must be the last header + +#endif // BOOST_SERIALIZER_MAP_HPP
diff --git a/boost/boost/archive/detail/check.hpp b/boost/boost/archive/detail/check.hpp new file mode 100644 index 0000000..10034e7 --- /dev/null +++ b/boost/boost/archive/detail/check.hpp
@@ -0,0 +1,169 @@ +#ifndef BOOST_ARCHIVE_DETAIL_CHECK_HPP +#define BOOST_ARCHIVE_DETAIL_CHECK_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#pragma inline_depth(511) +#pragma inline_recursion(on) +#endif + +#if defined(__MWERKS__) +#pragma inline_depth(511) +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// check.hpp: interface for serialization system. + +// (C) Copyright 2009 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> + +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_const.hpp> + +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/or.hpp> +#include <boost/mpl/equal_to.hpp> +#include <boost/mpl/int.hpp> +#include <boost/mpl/not.hpp> +#include <boost/mpl/greater.hpp> +#include <boost/mpl/assert.hpp> + +#include <boost/serialization/static_warning.hpp> +#include <boost/serialization/version.hpp> +#include <boost/serialization/level.hpp> +#include <boost/serialization/tracking.hpp> +#include <boost/serialization/wrapper.hpp> + +namespace boost { +namespace archive { +namespace detail { + +// checks for objects + +template<class T> +inline void check_object_level(){ + typedef + typename mpl::greater_equal< + serialization::implementation_level< T >, + mpl::int_<serialization::primitive_type> + >::type typex; + + // trap attempts to serialize objects marked + // not_serializable + BOOST_STATIC_ASSERT(typex::value); +} + +template<class T> +inline void check_object_versioning(){ + typedef + typename mpl::or_< + typename mpl::greater< + serialization::implementation_level< T >, + mpl::int_<serialization::object_serializable> + >, + typename mpl::equal_to< + serialization::version< T >, + mpl::int_<0> + > + > typex; + // trap attempts to serialize with objects that don't + // save class information in the archive with versioning. + BOOST_STATIC_ASSERT(typex::value); +} + +template<class T> +inline void check_object_tracking(){ + // presume it has already been determined that + // T is not a const + BOOST_STATIC_ASSERT(! boost::is_const< T >::value); + typedef typename mpl::equal_to< + serialization::tracking_level< T >, + mpl::int_<serialization::track_never> + >::type typex; + // saving an non-const object of a type not marked "track_never) + + // may be an indicator of an error usage of the + // serialization library and should be double checked. + // See documentation on object tracking. Also, see the + // "rationale" section of the documenation + // for motivation for this checking. + + BOOST_STATIC_WARNING(typex::value); +} + +// checks for pointers + +template<class T> +inline void check_pointer_level(){ + // we should only invoke this once we KNOW that T + // has been used as a pointer!! + typedef + typename mpl::or_< + typename mpl::greater< + serialization::implementation_level< T >, + mpl::int_<serialization::object_serializable> + >, + typename mpl::not_< + typename mpl::equal_to< + serialization::tracking_level< T >, + mpl::int_<serialization::track_selectively> + > + > + > typex; + // Address the following when serializing to a pointer: + + // a) This type doesn't save class information in the + // archive. That is, the serialization trait implementation + // level <= object_serializable. + // b) Tracking for this type is set to "track selectively" + + // in this case, indication that an object is tracked is + // not stored in the archive itself - see level == object_serializable + // but rather the existence of the operation ar >> T * is used to + // infer that an object of this type should be tracked. So, if + // you save via a pointer but don't load via a pointer the operation + // will fail on load without given any valid reason for the failure. + + // So if your program traps here, consider changing the + // tracking or implementation level traits - or not + // serializing via a pointer. + BOOST_STATIC_WARNING(typex::value); +} + +template<class T> +void inline check_pointer_tracking(){ + typedef typename mpl::greater< + serialization::tracking_level< T >, + mpl::int_<serialization::track_never> + >::type typex; + // serializing an object of a type marked "track_never" through a pointer + // could result in creating more objects than were saved! + BOOST_STATIC_WARNING(typex::value); +} + +template<class T> +inline void check_const_loading(){ + typedef + typename mpl::or_< + typename boost::serialization::is_wrapper< T >, + typename mpl::not_< + typename boost::is_const< T > + > + >::type typex; + // cannot load data into a "const" object unless it's a + // wrapper around some other non-const object. + BOOST_STATIC_ASSERT(typex::value); +} + +} // detail +} // archive +} // boost + +#endif // BOOST_ARCHIVE_DETAIL_CHECK_HPP
diff --git a/boost/boost/archive/detail/common_iarchive.hpp b/boost/boost/archive/detail/common_iarchive.hpp new file mode 100644 index 0000000..45e6d34 --- /dev/null +++ b/boost/boost/archive/detail/common_iarchive.hpp
@@ -0,0 +1,88 @@ +#ifndef BOOST_ARCHIVE_DETAIL_COMMON_IARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_COMMON_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// common_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> + +#include <boost/archive/detail/basic_iarchive.hpp> +#include <boost/archive/detail/basic_pointer_iserializer.hpp> +#include <boost/archive/detail/interface_iarchive.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { +namespace detail { + +class extended_type_info; + +// note: referred to as Curiously Recurring Template Patter (CRTP) +template<class Archive> +class common_iarchive : + public basic_iarchive, + public interface_iarchive<Archive> +{ + friend class interface_iarchive<Archive>; +private: + virtual void vload(version_type & t){ + * this->This() >> t; + } + virtual void vload(object_id_type & t){ + * this->This() >> t; + } + virtual void vload(class_id_type & t){ + * this->This() >> t; + } + virtual void vload(class_id_optional_type & t){ + * this->This() >> t; + } + virtual void vload(tracking_type & t){ + * this->This() >> t; + } + virtual void vload(class_name_type &s){ + * this->This() >> s; + } +protected: + // default processing - invoke serialization library + template<class T> + void load_override(T & t, BOOST_PFTO int){ + archive::load(* this->This(), t); + } + // default implementations of functions which emit start/end tags for + // archive types that require them. + void load_start(const char * /*name*/){} + void load_end(const char * /*name*/){} + // default archive initialization + common_iarchive(unsigned int flags = 0) : + basic_iarchive(flags), + interface_iarchive<Archive>() + {} +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_ARCHIVE_DETAIL_COMMON_IARCHIVE_HPP +
diff --git a/boost/boost/archive/detail/common_oarchive.hpp b/boost/boost/archive/detail/common_oarchive.hpp new file mode 100644 index 0000000..0d7474b --- /dev/null +++ b/boost/boost/archive/detail/common_oarchive.hpp
@@ -0,0 +1,87 @@ +#ifndef BOOST_ARCHIVE_DETAIL_COMMON_OARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_COMMON_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// common_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> + +#include <boost/archive/detail/basic_oarchive.hpp> +#include <boost/archive/detail/interface_oarchive.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { +namespace detail { + +// note: referred to as Curiously Recurring Template Patter (CRTP) +template<class Archive> +class common_oarchive : + public basic_oarchive, + public interface_oarchive<Archive> +{ + friend class interface_oarchive<Archive>; +private: + virtual void vsave(const version_type t){ + * this->This() << t; + } + virtual void vsave(const object_id_type t){ + * this->This() << t; + } + virtual void vsave(const object_reference_type t){ + * this->This() << t; + } + virtual void vsave(const class_id_type t){ + * this->This() << t; + } + virtual void vsave(const class_id_reference_type t){ + * this->This() << t; + } + virtual void vsave(const class_id_optional_type t){ + * this->This() << t; + } + virtual void vsave(const class_name_type & t){ + * this->This() << t; + } + virtual void vsave(const tracking_type t){ + * this->This() << t; + } +protected: + // default processing - invoke serialization library + template<class T> + void save_override(T & t, BOOST_PFTO int){ + archive::save(* this->This(), t); + } + void save_start(const char * /*name*/){} + void save_end(const char * /*name*/){} + common_oarchive(unsigned int flags = 0) : + basic_oarchive(flags), + interface_oarchive<Archive>() + {} +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_ARCHIVE_DETAIL_COMMON_OARCHIVE_HPP
diff --git a/boost/boost/archive/detail/decl.hpp b/boost/boost/archive/detail/decl.hpp new file mode 100644 index 0000000..44e22be --- /dev/null +++ b/boost/boost/archive/detail/decl.hpp
@@ -0,0 +1,79 @@ +#ifndef BOOST_ARCHIVE_DETAIL_DECL_HPP +#define BOOST_ARCHIVE_DETAIL_DECL_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2///////// 3/////////4/////////5/////////6/////////7/////////8 +// decl.hpp +// +// (c) Copyright Robert Ramey 2004 +// Use, modification, and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See library home page at http://www.boost.org/libs/serialization + +//----------------------------------------------------------------------------// + +// This header implements separate compilation features as described in +// http://www.boost.org/more/separate_compilation.html + +#include <boost/config.hpp> +#include <boost/preprocessor/facilities/empty.hpp> + +#if defined(BOOST_HAS_DECLSPEC) + #if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK)) + #if defined(BOOST_ARCHIVE_SOURCE) + #if defined(__BORLANDC__) + #define BOOST_ARCHIVE_DECL(T) T __export + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T __export + #else + #define BOOST_ARCHIVE_DECL(T) __declspec(dllexport) T + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) __declspec(dllexport) T + #endif + #else + #if defined(__BORLANDC__) + #define BOOST_ARCHIVE_DECL(T) T __import + #else + #define BOOST_ARCHIVE_DECL(T) __declspec(dllimport) T + #endif + #endif + #if defined(BOOST_WARCHIVE_SOURCE) + #if defined(__BORLANDC__) + #define BOOST_WARCHIVE_DECL(T) T __export + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T __export + #else + #define BOOST_WARCHIVE_DECL(T) __declspec(dllexport) T + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) __declspec(dllexport) T + #endif + #else + #if defined(__BORLANDC__) + #define BOOST_WARCHIVE_DECL(T) T __import + #else + #define BOOST_WARCHIVE_DECL(T) __declspec(dllimport) T + #endif + #endif + #if !defined(BOOST_WARCHIVE_SOURCE) && !defined(BOOST_ARCHIVE_SOURCE) + #if defined(__BORLANDC__) + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T __import + #else + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) __declspec(dllimport) T + #endif + #endif + #endif +#endif // BOOST_HAS_DECLSPEC + +#if ! defined(BOOST_ARCHIVE_DECL) + #define BOOST_ARCHIVE_DECL(T) T +#endif +#if ! defined(BOOST_WARCHIVE_DECL) + #define BOOST_WARCHIVE_DECL(T) T +#endif +#if ! defined(BOOST_ARCHIVE_OR_WARCHIVE_DECL) + #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T +#endif + +#endif // BOOST_ARCHIVE_DETAIL_DECL_HPP
diff --git a/boost/boost/archive/detail/helper_collection.hpp b/boost/boost/archive/detail/helper_collection.hpp new file mode 100644 index 0000000..cfa644f --- /dev/null +++ b/boost/boost/archive/detail/helper_collection.hpp
@@ -0,0 +1,98 @@ +#ifndef BOOST_ARCHIVE_DETAIL_HELPER_COLLECTION_HPP +#define BOOST_ARCHIVE_DETAIL_HELPER_COLLECTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// helper_collection.hpp: archive support for run-time helpers + +// (C) Copyright 2002-2008 Robert Ramey and Joaquin M Lopez Munoz +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstddef> // NULL +#include <vector> +#include <utility> +#include <memory> +#include <algorithm> + +#include <boost/config.hpp> + +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +namespace boost { + +namespace archive { +namespace detail { + +class helper_collection +{ + helper_collection(const helper_collection&); // non-copyable + helper_collection& operator = (const helper_collection&); // non-copyable + + // note: we dont' actually "share" the function object pointer + // we only use shared_ptr to make sure that it get's deleted + + typedef std::pair< + const void *, + boost::shared_ptr<void> + > helper_value_type; + template<class T> + boost::shared_ptr<void> make_helper_ptr(){ + // use boost::shared_ptr rather than std::shared_ptr to maintain + // c++03 compatibility + return boost::make_shared<T>(); + } + + typedef std::vector<helper_value_type> collection; + collection m_collection; + + struct predicate { + const void * const m_ti; + bool operator()(helper_value_type const &rhs) const { + return m_ti == rhs.first; + } + predicate & operator=(const void * ti); // to suppress warning + predicate(const void * ti) : + m_ti(ti) + {} + }; +protected: + helper_collection(){} + ~helper_collection(){} +public: + template<typename Helper> + Helper& get_helper(void * const id = 0) { + collection::const_iterator it = + std::find_if( + m_collection.begin(), + m_collection.end(), + predicate(id) + ); + + void * rval = 0; + if(it == m_collection.end()){ + m_collection.push_back( + std::make_pair(id, make_helper_ptr<Helper>()) + ); + rval = m_collection.back().second.get(); + } + else{ + rval = it->second.get(); + } + return *static_cast<Helper *>(rval); + } +}; + +} // namespace detail +} // namespace serialization +} // namespace boost + +#endif // BOOST_ARCHIVE_DETAIL_HELPER_COLLECTION_HPP
diff --git a/boost/boost/archive/detail/interface_iarchive.hpp b/boost/boost/archive/detail/interface_iarchive.hpp new file mode 100644 index 0000000..b7bd165 --- /dev/null +++ b/boost/boost/archive/detail/interface_iarchive.hpp
@@ -0,0 +1,77 @@ +#ifndef BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// interface_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. +#include <cstddef> // NULL +#include <boost/cstdint.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/iserializer.hpp> +#include <boost/serialization/singleton.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer; + +template<class Archive> +class interface_iarchive +{ +protected: + interface_iarchive(){}; +public: + ///////////////////////////////////////////////////////// + // archive public interface + typedef mpl::bool_<true> is_loading; + typedef mpl::bool_<false> is_saving; + + // return a pointer to the most derived class + Archive * This(){ + return static_cast<Archive *>(this); + } + + template<class T> + const basic_pointer_iserializer * + register_type(T * = NULL){ + const basic_pointer_iserializer & bpis = + boost::serialization::singleton< + pointer_iserializer<Archive, T> + >::get_const_instance(); + this->This()->register_basic_serializer(bpis.get_basic_serializer()); + return & bpis; + } + template<class T> + Archive & operator>>(T & t){ + this->This()->load_override(t, 0); + return * this->This(); + } + + // the & operator + template<class T> + Archive & operator&(T & t){ + return *(this->This()) >> t; + } +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP
diff --git a/boost/boost/archive/detail/interface_oarchive.hpp b/boost/boost/archive/detail/interface_oarchive.hpp new file mode 100644 index 0000000..7ae7176 --- /dev/null +++ b/boost/boost/archive/detail/interface_oarchive.hpp
@@ -0,0 +1,84 @@ +#ifndef BOOST_ARCHIVE_DETAIL_INTERFACE_OARCHIVE_HPP +#define BOOST_ARCHIVE_DETAIL_INTERFACE_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// interface_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. +#include <cstddef> // NULL +#include <boost/cstdint.hpp> +#include <boost/mpl/bool.hpp> + +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/detail/oserializer.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#include <boost/serialization/singleton.hpp> + +namespace boost { +namespace archive { +namespace detail { + +class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer; + +template<class Archive> +class interface_oarchive +{ +protected: + interface_oarchive(){}; +public: + ///////////////////////////////////////////////////////// + // archive public interface + typedef mpl::bool_<false> is_loading; + typedef mpl::bool_<true> is_saving; + + // return a pointer to the most derived class + Archive * This(){ + return static_cast<Archive *>(this); + } + + template<class T> + const basic_pointer_oserializer * + register_type(const T * = NULL){ + const basic_pointer_oserializer & bpos = + boost::serialization::singleton< + pointer_oserializer<Archive, T> + >::get_const_instance(); + this->This()->register_basic_serializer(bpos.get_basic_serializer()); + return & bpos; + } + + template<class T> + Archive & operator<<(T & t){ + this->This()->save_override(t, 0); + return * this->This(); + } + + // the & operator + template<class T> + Archive & operator&(T & t){ + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + return * this->This() << const_cast<const T &>(t); + #else + return * this->This() << t; + #endif + } +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP
diff --git a/boost/boost/archive/detail/iserializer.hpp b/boost/boost/archive/detail/iserializer.hpp new file mode 100644 index 0000000..65dfe8e --- /dev/null +++ b/boost/boost/archive/detail/iserializer.hpp
@@ -0,0 +1,658 @@ +#ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP +#define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#pragma inline_depth(511) +#pragma inline_recursion(on) +#endif + +#if defined(__MWERKS__) +#pragma inline_depth(511) +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// iserializer.hpp: interface for serialization system. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <new> // for placement new +#include <cstddef> // size_t, NULL + +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/static_assert.hpp> + +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/identity.hpp> +#include <boost/mpl/greater_equal.hpp> +#include <boost/mpl/equal_to.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/core/no_exceptions_support.hpp> + +#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO + #include <boost/serialization/extended_type_info_typeid.hpp> +#endif +#include <boost/serialization/throw_exception.hpp> +#include <boost/serialization/smart_cast.hpp> +#include <boost/serialization/static_warning.hpp> + +#include <boost/type_traits/is_pointer.hpp> +#include <boost/type_traits/is_enum.hpp> +#include <boost/type_traits/is_const.hpp> +#include <boost/type_traits/remove_const.hpp> +#include <boost/type_traits/remove_extent.hpp> +#include <boost/type_traits/is_polymorphic.hpp> + +#include <boost/serialization/assume_abstract.hpp> +#define DONT_USE_HAS_NEW_OPERATOR ( \ + defined(__BORLANDC__) \ + || BOOST_WORKAROUND(__IBMCPP__, < 1210) \ + || defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590) \ +) +#if ! DONT_USE_HAS_NEW_OPERATOR +#include <boost/type_traits/has_new_operator.hpp> +#endif + +#include <boost/serialization/serialization.hpp> +#include <boost/serialization/version.hpp> +#include <boost/serialization/level.hpp> +#include <boost/serialization/tracking.hpp> +#include <boost/serialization/type_info_implementation.hpp> +#include <boost/serialization/nvp.hpp> +#include <boost/serialization/void_cast.hpp> +#include <boost/serialization/array.hpp> +#include <boost/serialization/collection_size_type.hpp> +#include <boost/serialization/singleton.hpp> +#include <boost/serialization/wrapper.hpp> + +// the following is need only for dynamic cast of polymorphic pointers +#include <boost/archive/archive_exception.hpp> +#include <boost/archive/detail/basic_iarchive.hpp> +#include <boost/archive/detail/basic_iserializer.hpp> +#include <boost/archive/detail/basic_pointer_iserializer.hpp> +#include <boost/archive/detail/archive_serializer_map.hpp> +#include <boost/archive/detail/check.hpp> + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { + +// an accessor to permit friend access to archives. Needed because +// some compilers don't handle friend templates completely +class load_access { +public: + template<class Archive, class T> + static void load_primitive(Archive &ar, T &t){ + ar.load(t); + } +}; + +namespace detail { + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +template<class Archive, class T> +class iserializer : public basic_iserializer +{ +private: + virtual void destroy(/*const*/ void *address) const { + boost::serialization::access::destroy(static_cast<T *>(address)); + } +protected: + // protected constructor since it's always created by singleton + explicit iserializer() : + basic_iserializer( + boost::serialization::singleton< + typename + boost::serialization::type_info_implementation< T >::type + >::get_const_instance() + ) + {} +public: + virtual BOOST_DLLEXPORT void load_object_data( + basic_iarchive & ar, + void *x, + const unsigned int file_version + ) const BOOST_USED; + virtual bool class_info() const { + return boost::serialization::implementation_level< T >::value + >= boost::serialization::object_class_info; + } + virtual bool tracking(const unsigned int /* flags */) const { + return boost::serialization::tracking_level< T >::value + == boost::serialization::track_always + || ( boost::serialization::tracking_level< T >::value + == boost::serialization::track_selectively + && serialized_as_pointer()); + } + virtual version_type version() const { + return version_type(::boost::serialization::version< T >::value); + } + virtual bool is_polymorphic() const { + return boost::is_polymorphic< T >::value; + } + virtual ~iserializer(){}; +}; + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +template<class Archive, class T> +BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data( + basic_iarchive & ar, + void *x, + const unsigned int file_version +) const { + // note: we now comment this out. Before we permited archive + // version # to be very large. Now we don't. To permit + // readers of these old archives, we have to suppress this + // code. Perhaps in the future we might re-enable it but + // permit its suppression with a runtime switch. + #if 0 + // trap case where the program cannot handle the current version + if(file_version > static_cast<const unsigned int>(version())) + boost::serialization::throw_exception( + archive::archive_exception( + boost::archive::archive_exception::unsupported_class_version, + get_debug_info() + ) + ); + #endif + // make sure call is routed through the higest interface that might + // be specialized by the user. + boost::serialization::serialize_adl( + boost::serialization::smart_cast_reference<Archive &>(ar), + * static_cast<T *>(x), + file_version + ); +} + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +// the purpose of this code is to allocate memory for an object +// without requiring the constructor to be called. Presumably +// the allocated object will be subsequently initialized with +// "placement new". +// note: we have the boost type trait has_new_operator but we +// have no corresponding has_delete_operator. So we presume +// that the former being true would imply that the a delete +// operator is also defined for the class T. + +template<class T> +struct heap_allocation { + // boost::has_new_operator< T > doesn't work on these compilers + #if DONT_USE_HAS_NEW_OPERATOR + // This doesn't handle operator new overload for class T + static T * invoke_new(){ + return static_cast<T *>(operator new(sizeof(T))); + } + static void invoke_delete(T *t){ + (operator delete(t)); + } + #else + // note: we presume that a true value for has_new_operator + // implies the existence of a class specific delete operator as well + // as a class specific new operator. + struct has_new_operator { + static T * invoke_new() { + return static_cast<T *>((T::operator new)(sizeof(T))); + } + static void invoke_delete(T * t) { + // if compilation fails here, the likely cause that the class + // T has a class specific new operator but no class specific + // delete operator which matches the following signature. Fix + // your program to have this. Note that adding operator delete + // with only one parameter doesn't seem correct to me since + // the standard(3.7.4.2) says " + // "If a class T has a member deallocation function named + // 'operator delete' with exactly one parameter, then that function + // is a usual (non-placement) deallocation function" which I take + // to mean that it will call the destructor of type T which we don't + // want to do here. + // Note: reliance upon automatic conversion from T * to void * here + (T::operator delete)(t, sizeof(T)); + } + }; + struct doesnt_have_new_operator { + static T* invoke_new() { + return static_cast<T *>(operator new(sizeof(T))); + } + static void invoke_delete(T * t) { + // Note: I'm reliance upon automatic conversion from T * to void * here + (operator delete)(t); + } + }; + static T * invoke_new() { + typedef typename + mpl::eval_if< + boost::has_new_operator< T >, + mpl::identity<has_new_operator >, + mpl::identity<doesnt_have_new_operator > + >::type typex; + return typex::invoke_new(); + } + static void invoke_delete(T *t) { + typedef typename + mpl::eval_if< + boost::has_new_operator< T >, + mpl::identity<has_new_operator >, + mpl::identity<doesnt_have_new_operator > + >::type typex; + typex::invoke_delete(t); + } + #endif + explicit heap_allocation(){ + m_p = invoke_new(); + } + ~heap_allocation(){ + if (0 != m_p) + invoke_delete(m_p); + } + T* get() const { + return m_p; + } + + T* release() { + T* p = m_p; + m_p = 0; + return p; + } +private: + T* m_p; +}; + +template<class Archive, class T> +class pointer_iserializer : + public basic_pointer_iserializer +{ +private: + virtual void * heap_allocation() const { + detail::heap_allocation<T> h; + T * t = h.get(); + h.release(); + return t; + } + virtual const basic_iserializer & get_basic_serializer() const { + return boost::serialization::singleton< + iserializer<Archive, T> + >::get_const_instance(); + } + BOOST_DLLEXPORT virtual void load_object_ptr( + basic_iarchive & ar, + void * x, + const unsigned int file_version + ) const BOOST_USED; +protected: + // this should alway be a singleton so make the constructor protected + pointer_iserializer(); + ~pointer_iserializer(); +}; + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +// note: BOOST_DLLEXPORT is so that code for polymorphic class +// serialized only through base class won't get optimized out +template<class Archive, class T> +BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr( + basic_iarchive & ar, + void * t, + const unsigned int file_version +) const +{ + Archive & ar_impl = + boost::serialization::smart_cast_reference<Archive &>(ar); + + // note that the above will throw std::bad_alloc if the allocation + // fails so we don't have to address this contingency here. + + // catch exception during load_construct_data so that we don't + // automatically delete the t which is most likely not fully + // constructed + BOOST_TRY { + // this addresses an obscure situation that occurs when + // load_constructor de-serializes something through a pointer. + ar.next_object_pointer(t); + boost::serialization::load_construct_data_adl<Archive, T>( + ar_impl, + static_cast<T *>(t), + file_version + ); + } + BOOST_CATCH(...){ + // if we get here the load_construct failed. The heap_allocation + // will be automatically deleted so we don't have to do anything + // special here. + BOOST_RETHROW; + } + BOOST_CATCH_END + + ar_impl >> boost::serialization::make_nvp(NULL, * static_cast<T *>(t)); +} + +template<class Archive, class T> +pointer_iserializer<Archive, T>::pointer_iserializer() : + basic_pointer_iserializer( + boost::serialization::singleton< + typename + boost::serialization::type_info_implementation< T >::type + >::get_const_instance() + ) +{ + boost::serialization::singleton< + iserializer<Archive, T> + >::get_mutable_instance().set_bpis(this); + archive_serializer_map<Archive>::insert(this); +} + +template<class Archive, class T> +pointer_iserializer<Archive, T>::~pointer_iserializer(){ + archive_serializer_map<Archive>::erase(this); +} + +template<class Archive> +struct load_non_pointer_type { + // note this bounces the call right back to the archive + // with no runtime overhead + struct load_primitive { + template<class T> + static void invoke(Archive & ar, T & t){ + load_access::load_primitive(ar, t); + } + }; + // note this bounces the call right back to the archive + // with no runtime overhead + struct load_only { + template<class T> + static void invoke(Archive & ar, const T & t){ + // short cut to user's serializer + // make sure call is routed through the higest interface that might + // be specialized by the user. + boost::serialization::serialize_adl( + ar, + const_cast<T &>(t), + boost::serialization::version< T >::value + ); + } + }; + + // note this save class information including version + // and serialization level to the archive + struct load_standard { + template<class T> + static void invoke(Archive &ar, const T & t){ + void * x = & const_cast<T &>(t); + ar.load_object( + x, + boost::serialization::singleton< + iserializer<Archive, T> + >::get_const_instance() + ); + } + }; + + struct load_conditional { + template<class T> + static void invoke(Archive &ar, T &t){ + //if(0 == (ar.get_flags() & no_tracking)) + load_standard::invoke(ar, t); + //else + // load_only::invoke(ar, t); + } + }; + + template<class T> + static void invoke(Archive & ar, T &t){ + typedef typename mpl::eval_if< + // if its primitive + mpl::equal_to< + boost::serialization::implementation_level< T >, + mpl::int_<boost::serialization::primitive_type> + >, + mpl::identity<load_primitive>, + // else + typename mpl::eval_if< + // class info / version + mpl::greater_equal< + boost::serialization::implementation_level< T >, + mpl::int_<boost::serialization::object_class_info> + >, + // do standard load + mpl::identity<load_standard>, + // else + typename mpl::eval_if< + // no tracking + mpl::equal_to< + boost::serialization::tracking_level< T >, + mpl::int_<boost::serialization::track_never> + >, + // do a fast load + mpl::identity<load_only>, + // else + // do a fast load only tracking is turned off + mpl::identity<load_conditional> + > > >::type typex; + check_object_versioning< T >(); + check_object_level< T >(); + typex::invoke(ar, t); + } +}; + +template<class Archive> +struct load_pointer_type { + struct abstract + { + template<class T> + static const basic_pointer_iserializer * register_type(Archive & /* ar */){ + // it has? to be polymorphic + BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value); + return static_cast<basic_pointer_iserializer *>(NULL); + } + }; + + struct non_abstract + { + template<class T> + static const basic_pointer_iserializer * register_type(Archive & ar){ + return ar.register_type(static_cast<T *>(NULL)); + } + }; + + template<class T> + static const basic_pointer_iserializer * register_type(Archive &ar, const T & /*t*/){ + // there should never be any need to load an abstract polymorphic + // class pointer. Inhibiting code generation for this + // permits abstract base classes to be used - note: exception + // virtual serialize functions used for plug-ins + typedef typename + mpl::eval_if< + boost::serialization::is_abstract<const T>, + boost::mpl::identity<abstract>, + boost::mpl::identity<non_abstract> + >::type typex; + return typex::template register_type< T >(ar); + } + + template<class T> + static T * pointer_tweak( + const boost::serialization::extended_type_info & eti, + void const * const t, + const T & + ) { + // tweak the pointer back to the base class + void * upcast = const_cast<void *>( + boost::serialization::void_upcast( + eti, + boost::serialization::singleton< + typename + boost::serialization::type_info_implementation< T >::type + >::get_const_instance(), + t + ) + ); + if(NULL == upcast) + boost::serialization::throw_exception( + archive_exception(archive_exception::unregistered_class) + ); + return static_cast<T *>(upcast); + } + + template<class T> + static void check_load(T & /* t */){ + check_pointer_level< T >(); + check_pointer_tracking< T >(); + } + + static const basic_pointer_iserializer * + find(const boost::serialization::extended_type_info & type){ + return static_cast<const basic_pointer_iserializer *>( + archive_serializer_map<Archive>::find(type) + ); + } + + template<class Tptr> + static void invoke(Archive & ar, Tptr & t){ + check_load(*t); + const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t); + const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer( + // note major hack here !!! + // I tried every way to convert Tptr &t (where Tptr might + // include const) to void * &. This is the only way + // I could make it work. RR + (void * & )t, + bpis_ptr, + find + ); + // if the pointer isn't that of the base class + if(newbpis_ptr != bpis_ptr){ + t = pointer_tweak(newbpis_ptr->get_eti(), t, *t); + } + } +}; + +template<class Archive> +struct load_enum_type { + template<class T> + static void invoke(Archive &ar, T &t){ + // convert integers to correct enum to load + int i; + ar >> boost::serialization::make_nvp(NULL, i); + t = static_cast< T >(i); + } +}; + +template<class Archive> +struct load_array_type { + template<class T> + static void invoke(Archive &ar, T &t){ + typedef typename remove_extent< T >::type value_type; + + // convert integers to correct enum to load + // determine number of elements in the array. Consider the + // fact that some machines will align elements on boundries + // other than characters. + std::size_t current_count = sizeof(t) / ( + static_cast<char *>(static_cast<void *>(&t[1])) + - static_cast<char *>(static_cast<void *>(&t[0])) + ); + boost::serialization::collection_size_type count; + ar >> BOOST_SERIALIZATION_NVP(count); + if(static_cast<std::size_t>(count) > current_count) + boost::serialization::throw_exception( + archive::archive_exception( + boost::archive::archive_exception::array_size_too_short + ) + ); + ar >> serialization::make_array(static_cast<value_type*>(&t[0]),count); + } +}; + +} // detail + +template<class Archive, class T> +inline void load(Archive & ar, T &t){ + // if this assertion trips. It means we're trying to load a + // const object with a compiler that doesn't have correct + // funtion template ordering. On other compilers, this is + // handled below. + detail::check_const_loading< T >(); + typedef + typename mpl::eval_if<is_pointer< T >, + mpl::identity<detail::load_pointer_type<Archive> > + ,//else + typename mpl::eval_if<is_array< T >, + mpl::identity<detail::load_array_type<Archive> > + ,//else + typename mpl::eval_if<is_enum< T >, + mpl::identity<detail::load_enum_type<Archive> > + ,//else + mpl::identity<detail::load_non_pointer_type<Archive> > + > + > + >::type typex; + typex::invoke(ar, t); +} + +#if 0 + +// BORLAND +#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) +// borland has a couple of problems +// a) if function is partially specialized - see below +// const paramters are transformed to non-const ones +// b) implementation of base_object can't be made to work +// correctly which results in all base_object s being const. +// So, strip off the const for borland. This breaks the trap +// for loading const objects - but I see no alternative +template<class Archive, class T> +inline void load(Archive &ar, const T & t){ + load(ar, const_cast<T &>(t)); +} +#endif + +// let wrappers through. +#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING +template<class Archive, class T> +inline void load_wrapper(Archive &ar, const T&t, mpl::true_){ + boost::archive::load(ar, const_cast<T&>(t)); +} + +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560)) +template<class Archive, class T> +inline void load(Archive &ar, const T&t){ + load_wrapper(ar,t,serialization::is_wrapper< T >()); +} +#endif +#endif + +#endif + +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
diff --git a/boost/boost/archive/detail/oserializer.hpp b/boost/boost/archive/detail/oserializer.hpp new file mode 100644 index 0000000..7a7e239 --- /dev/null +++ b/boost/boost/archive/detail/oserializer.hpp
@@ -0,0 +1,531 @@ +#ifndef BOOST_ARCHIVE_OSERIALIZER_HPP +#define BOOST_ARCHIVE_OSERIALIZER_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#pragma inline_depth(511) +#pragma inline_recursion(on) +#endif + +#if defined(__MWERKS__) +#pragma inline_depth(511) +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// oserializer.hpp: interface for serialization system. + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> +#include <cstddef> // NULL + +#include <boost/config.hpp> +#include <boost/static_assert.hpp> +#include <boost/detail/workaround.hpp> + +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/equal_to.hpp> +#include <boost/mpl/greater_equal.hpp> +#include <boost/mpl/identity.hpp> + +#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO + #include <boost/serialization/extended_type_info_typeid.hpp> +#endif +#include <boost/serialization/throw_exception.hpp> +#include <boost/serialization/smart_cast.hpp> +#include <boost/serialization/assume_abstract.hpp> +#include <boost/serialization/static_warning.hpp> + +#include <boost/type_traits/is_pointer.hpp> +#include <boost/type_traits/is_enum.hpp> +#include <boost/type_traits/is_const.hpp> +#include <boost/type_traits/is_polymorphic.hpp> +#include <boost/type_traits/remove_extent.hpp> + +#include <boost/serialization/serialization.hpp> +#include <boost/serialization/version.hpp> +#include <boost/serialization/level.hpp> +#include <boost/serialization/tracking.hpp> +#include <boost/serialization/type_info_implementation.hpp> +#include <boost/serialization/nvp.hpp> +#include <boost/serialization/void_cast.hpp> +#include <boost/serialization/array.hpp> +#include <boost/serialization/collection_size_type.hpp> +#include <boost/serialization/singleton.hpp> + +#include <boost/archive/archive_exception.hpp> +#include <boost/archive/detail/basic_oarchive.hpp> +#include <boost/archive/detail/basic_oserializer.hpp> +#include <boost/archive/detail/basic_pointer_oserializer.hpp> +#include <boost/archive/detail/archive_serializer_map.hpp> +#include <boost/archive/detail/check.hpp> + +namespace boost { + +namespace serialization { + class extended_type_info; +} // namespace serialization + +namespace archive { + +// an accessor to permit friend access to archives. Needed because +// some compilers don't handle friend templates completely +class save_access { +public: + template<class Archive> + static void end_preamble(Archive & ar){ + ar.end_preamble(); + } + template<class Archive, class T> + static void save_primitive(Archive & ar, const T & t){ + ar.end_preamble(); + ar.save(t); + } +}; + +namespace detail { + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +template<class Archive, class T> +class oserializer : public basic_oserializer +{ +private: + // private constructor to inhibit any existence other than the + // static one +public: + explicit BOOST_DLLEXPORT oserializer() : + basic_oserializer( + boost::serialization::singleton< + typename + boost::serialization::type_info_implementation< T >::type + >::get_const_instance() + ) + {} + virtual BOOST_DLLEXPORT void save_object_data( + basic_oarchive & ar, + const void *x + ) const BOOST_USED; + virtual bool class_info() const { + return boost::serialization::implementation_level< T >::value + >= boost::serialization::object_class_info; + } + virtual bool tracking(const unsigned int /* flags */) const { + return boost::serialization::tracking_level< T >::value == boost::serialization::track_always + || (boost::serialization::tracking_level< T >::value == boost::serialization::track_selectively + && serialized_as_pointer()); + } + virtual version_type version() const { + return version_type(::boost::serialization::version< T >::value); + } + virtual bool is_polymorphic() const { + return boost::is_polymorphic< T >::value; + } + virtual ~oserializer(){} +}; + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +template<class Archive, class T> +BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data( + basic_oarchive & ar, + const void *x +) const { + // make sure call is routed through the highest interface that might + // be specialized by the user. + BOOST_STATIC_ASSERT(boost::is_const< T >::value == false); + boost::serialization::serialize_adl( + boost::serialization::smart_cast_reference<Archive &>(ar), + * static_cast<T *>(const_cast<void *>(x)), + version() + ); +} + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +template<class Archive, class T> +class pointer_oserializer : + public basic_pointer_oserializer +{ +private: + const basic_oserializer & + get_basic_serializer() const { + return boost::serialization::singleton< + oserializer<Archive, T> + >::get_const_instance(); + } + virtual BOOST_DLLEXPORT void save_object_ptr( + basic_oarchive & ar, + const void * x + ) const BOOST_USED; +public: + pointer_oserializer(); + ~pointer_oserializer(); +}; + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +template<class Archive, class T> +BOOST_DLLEXPORT void pointer_oserializer<Archive, T>::save_object_ptr( + basic_oarchive & ar, + const void * x +) const { + BOOST_ASSERT(NULL != x); + // make sure call is routed through the highest interface that might + // be specialized by the user. + T * t = static_cast<T *>(const_cast<void *>(x)); + const unsigned int file_version = boost::serialization::version< T >::value; + Archive & ar_impl + = boost::serialization::smart_cast_reference<Archive &>(ar); + boost::serialization::save_construct_data_adl<Archive, T>( + ar_impl, + t, + file_version + ); + ar_impl << boost::serialization::make_nvp(NULL, * t); +} + +template<class Archive, class T> +pointer_oserializer<Archive, T>::pointer_oserializer() : + basic_pointer_oserializer( + boost::serialization::singleton< + typename + boost::serialization::type_info_implementation< T >::type + >::get_const_instance() + ) +{ + // make sure appropriate member function is instantiated + boost::serialization::singleton< + oserializer<Archive, T> + >::get_mutable_instance().set_bpos(this); + archive_serializer_map<Archive>::insert(this); +} + +template<class Archive, class T> +pointer_oserializer<Archive, T>::~pointer_oserializer(){ + archive_serializer_map<Archive>::erase(this); +} + +template<class Archive> +struct save_non_pointer_type { + // note this bounces the call right back to the archive + // with no runtime overhead + struct save_primitive { + template<class T> + static void invoke(Archive & ar, const T & t){ + save_access::save_primitive(ar, t); + } + }; + // same as above but passes through serialization + struct save_only { + template<class T> + static void invoke(Archive & ar, const T & t){ + // make sure call is routed through the highest interface that might + // be specialized by the user. + boost::serialization::serialize_adl( + ar, + const_cast<T &>(t), + ::boost::serialization::version< T >::value + ); + } + }; + // adds class information to the archive. This includes + // serialization level and class version + struct save_standard { + template<class T> + static void invoke(Archive &ar, const T & t){ + ar.save_object( + & t, + boost::serialization::singleton< + oserializer<Archive, T> + >::get_const_instance() + ); + } + }; + + // adds class information to the archive. This includes + // serialization level and class version + struct save_conditional { + template<class T> + static void invoke(Archive &ar, const T &t){ + //if(0 == (ar.get_flags() & no_tracking)) + save_standard::invoke(ar, t); + //else + // save_only::invoke(ar, t); + } + }; + + + template<class T> + static void invoke(Archive & ar, const T & t){ + typedef + typename mpl::eval_if< + // if its primitive + mpl::equal_to< + boost::serialization::implementation_level< T >, + mpl::int_<boost::serialization::primitive_type> + >, + mpl::identity<save_primitive>, + // else + typename mpl::eval_if< + // class info / version + mpl::greater_equal< + boost::serialization::implementation_level< T >, + mpl::int_<boost::serialization::object_class_info> + >, + // do standard save + mpl::identity<save_standard>, + // else + typename mpl::eval_if< + // no tracking + mpl::equal_to< + boost::serialization::tracking_level< T >, + mpl::int_<boost::serialization::track_never> + >, + // do a fast save + mpl::identity<save_only>, + // else + // do a fast save only tracking is turned off + mpl::identity<save_conditional> + > > >::type typex; + check_object_versioning< T >(); + typex::invoke(ar, t); + } + template<class T> + static void invoke(Archive & ar, T & t){ + check_object_level< T >(); + check_object_tracking< T >(); + invoke(ar, const_cast<const T &>(t)); + } +}; + +template<class Archive> +struct save_pointer_type { + struct abstract + { + template<class T> + static const basic_pointer_oserializer * register_type(Archive & /* ar */){ + // it has? to be polymorphic + BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value); + return NULL; + } + }; + + struct non_abstract + { + template<class T> + static const basic_pointer_oserializer * register_type(Archive & ar){ + return ar.register_type(static_cast<T *>(NULL)); + } + }; + + template<class T> + static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){ + // there should never be any need to save an abstract polymorphic + // class pointer. Inhibiting code generation for this + // permits abstract base classes to be used - note: exception + // virtual serialize functions used for plug-ins + typedef + typename mpl::eval_if< + boost::serialization::is_abstract< T >, + mpl::identity<abstract>, + mpl::identity<non_abstract> + >::type typex; + return typex::template register_type< T >(ar); + } + + struct non_polymorphic + { + template<class T> + static void save( + Archive &ar, + T & t + ){ + const basic_pointer_oserializer & bpos = + boost::serialization::singleton< + pointer_oserializer<Archive, T> + >::get_const_instance(); + // save the requested pointer type + ar.save_pointer(& t, & bpos); + } + }; + + struct polymorphic + { + template<class T> + static void save( + Archive &ar, + T & t + ){ + typename + boost::serialization::type_info_implementation< T >::type const + & i = boost::serialization::singleton< + typename + boost::serialization::type_info_implementation< T >::type + >::get_const_instance(); + + boost::serialization::extended_type_info const * const this_type = & i; + + // retrieve the true type of the object pointed to + // if this assertion fails its an error in this library + BOOST_ASSERT(NULL != this_type); + + const boost::serialization::extended_type_info * true_type = + i.get_derived_extended_type_info(t); + + // note:if this exception is thrown, be sure that derived pointer + // is either registered or exported. + if(NULL == true_type){ + boost::serialization::throw_exception( + archive_exception( + archive_exception::unregistered_class, + "derived class not registered or exported" + ) + ); + } + + // if its not a pointer to a more derived type + const void *vp = static_cast<const void *>(&t); + if(*this_type == *true_type){ + const basic_pointer_oserializer * bpos = register_type(ar, t); + ar.save_pointer(vp, bpos); + return; + } + // convert pointer to more derived type. if this is thrown + // it means that the base/derived relationship hasn't be registered + vp = serialization::void_downcast( + *true_type, + *this_type, + static_cast<const void *>(&t) + ); + if(NULL == vp){ + boost::serialization::throw_exception( + archive_exception( + archive_exception::unregistered_cast, + true_type->get_debug_info(), + this_type->get_debug_info() + ) + ); + } + + // since true_type is valid, and this only gets made if the + // pointer oserializer object has been created, this should never + // fail + const basic_pointer_oserializer * bpos + = static_cast<const basic_pointer_oserializer *>( + boost::serialization::singleton< + archive_serializer_map<Archive> + >::get_const_instance().find(*true_type) + ); + BOOST_ASSERT(NULL != bpos); + if(NULL == bpos) + boost::serialization::throw_exception( + archive_exception( + archive_exception::unregistered_class, + "derived class not registered or exported" + ) + ); + ar.save_pointer(vp, bpos); + } + }; + + template<class T> + static void save( + Archive & ar, + const T & t + ){ + check_pointer_level< T >(); + check_pointer_tracking< T >(); + typedef typename mpl::eval_if< + is_polymorphic< T >, + mpl::identity<polymorphic>, + mpl::identity<non_polymorphic> + >::type type; + type::save(ar, const_cast<T &>(t)); + } + + template<class TPtr> + static void invoke(Archive &ar, const TPtr t){ + register_type(ar, * t); + if(NULL == t){ + basic_oarchive & boa + = boost::serialization::smart_cast_reference<basic_oarchive &>(ar); + boa.save_null_pointer(); + save_access::end_preamble(ar); + return; + } + save(ar, * t); + } +}; + +template<class Archive> +struct save_enum_type +{ + template<class T> + static void invoke(Archive &ar, const T &t){ + // convert enum to integers on save + const int i = static_cast<int>(t); + ar << boost::serialization::make_nvp(NULL, i); + } +}; + +template<class Archive> +struct save_array_type +{ + template<class T> + static void invoke(Archive &ar, const T &t){ + typedef typename boost::remove_extent< T >::type value_type; + + save_access::end_preamble(ar); + // consider alignment + std::size_t c = sizeof(t) / ( + static_cast<const char *>(static_cast<const void *>(&t[1])) + - static_cast<const char *>(static_cast<const void *>(&t[0])) + ); + boost::serialization::collection_size_type count(c); + ar << BOOST_SERIALIZATION_NVP(count); + ar << serialization::make_array(static_cast<value_type const*>(&t[0]),count); + } +}; + +} // detail + +template<class Archive, class T> +inline void save(Archive & ar, /*const*/ T &t){ + typedef + typename mpl::eval_if<is_pointer< T >, + mpl::identity<detail::save_pointer_type<Archive> >, + //else + typename mpl::eval_if<is_enum< T >, + mpl::identity<detail::save_enum_type<Archive> >, + //else + typename mpl::eval_if<is_array< T >, + mpl::identity<detail::save_array_type<Archive> >, + //else + mpl::identity<detail::save_non_pointer_type<Archive> > + > + > + >::type typex; + typex::invoke(ar, t); +} + +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_OSERIALIZER_HPP
diff --git a/boost/boost/archive/detail/polymorphic_iarchive_route.hpp b/boost/boost/archive/detail/polymorphic_iarchive_route.hpp new file mode 100644 index 0000000..a8eb7aa --- /dev/null +++ b/boost/boost/archive/detail/polymorphic_iarchive_route.hpp
@@ -0,0 +1,215 @@ +#ifndef BOOST_ARCHIVE_DETAIL_POLYMORPHIC_IARCHIVE_ROUTE_HPP +#define BOOST_ARCHIVE_DETAIL_POLYMORPHIC_IARCHIVE_ROUTE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_iarchive_route.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <string> +#include <ostream> +#include <cstddef> + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/cstdint.hpp> +#include <boost/integer_traits.hpp> +#include <boost/archive/polymorphic_iarchive.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization +namespace archive { +namespace detail{ + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer; + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +template<class ArchiveImplementation> +class polymorphic_iarchive_route : + public polymorphic_iarchive, + // note: gcc dynamic cross cast fails if the the derivation below is + // not public. I think this is a mistake. + public /*protected*/ ArchiveImplementation +{ +private: + // these are used by the serialization library. + virtual void load_object( + void *t, + const basic_iserializer & bis + ){ + ArchiveImplementation::load_object(t, bis); + } + virtual const basic_pointer_iserializer * load_pointer( + void * & t, + const basic_pointer_iserializer * bpis_ptr, + const basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type + ) + ){ + return ArchiveImplementation::load_pointer(t, bpis_ptr, finder); + } + virtual void set_library_version(library_version_type archive_library_version){ + ArchiveImplementation::set_library_version(archive_library_version); + } + virtual library_version_type get_library_version() const{ + return ArchiveImplementation::get_library_version(); + } + virtual unsigned int get_flags() const { + return ArchiveImplementation::get_flags(); + } + virtual void delete_created_pointers(){ + ArchiveImplementation::delete_created_pointers(); + } + virtual void reset_object_address( + const void * new_address, + const void * old_address + ){ + ArchiveImplementation::reset_object_address(new_address, old_address); + } + virtual void load_binary(void * t, std::size_t size){ + ArchiveImplementation::load_binary(t, size); + } + // primitive types the only ones permitted by polymorphic archives + virtual void load(bool & t){ + ArchiveImplementation::load(t); + } + virtual void load(char & t){ + ArchiveImplementation::load(t); + } + virtual void load(signed char & t){ + ArchiveImplementation::load(t); + } + virtual void load(unsigned char & t){ + ArchiveImplementation::load(t); + } + #ifndef BOOST_NO_CWCHAR + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + virtual void load(wchar_t & t){ + ArchiveImplementation::load(t); + } + #endif + #endif + virtual void load(short & t){ + ArchiveImplementation::load(t); + } + virtual void load(unsigned short & t){ + ArchiveImplementation::load(t); + } + virtual void load(int & t){ + ArchiveImplementation::load(t); + } + virtual void load(unsigned int & t){ + ArchiveImplementation::load(t); + } + virtual void load(long & t){ + ArchiveImplementation::load(t); + } + virtual void load(unsigned long & t){ + ArchiveImplementation::load(t); + } + #if defined(BOOST_HAS_LONG_LONG) + virtual void load(boost::long_long_type & t){ + ArchiveImplementation::load(t); + } + virtual void load(boost::ulong_long_type & t){ + ArchiveImplementation::load(t); + } + #elif defined(BOOST_HAS_MS_INT64) + virtual void load(__int64 & t){ + ArchiveImplementation::load(t); + } + virtual void load(unsigned __int64 & t){ + ArchiveImplementation::load(t); + } + #endif + virtual void load(float & t){ + ArchiveImplementation::load(t); + } + virtual void load(double & t){ + ArchiveImplementation::load(t); + } + virtual void load(std::string & t){ + ArchiveImplementation::load(t); + } + #ifndef BOOST_NO_STD_WSTRING + virtual void load(std::wstring & t){ + ArchiveImplementation::load(t); + } + #endif + // used for xml and other tagged formats default does nothing + virtual void load_start(const char * name){ + ArchiveImplementation::load_start(name); + } + virtual void load_end(const char * name){ + ArchiveImplementation::load_end(name); + } + + virtual void register_basic_serializer(const basic_iserializer & bis){ + ArchiveImplementation::register_basic_serializer(bis); + } +public: + // this can't be inheriteded because they appear in mulitple + // parents + typedef mpl::bool_<true> is_loading; + typedef mpl::bool_<false> is_saving; + // the >> operator + template<class T> + polymorphic_iarchive & operator>>(T & t){ + return polymorphic_iarchive::operator>>(t); + } + // the & operator + template<class T> + polymorphic_iarchive & operator&(T & t){ + return polymorphic_iarchive::operator&(t); + } + // register type function + template<class T> + const basic_pointer_iserializer * + register_type(T * t = NULL){ + return ArchiveImplementation::register_type(t); + } + // all current archives take a stream as constructor argument + template <class _Elem, class _Tr> + polymorphic_iarchive_route( + std::basic_istream<_Elem, _Tr> & is, + unsigned int flags = 0 + ) : + ArchiveImplementation(is, flags) + {} + virtual ~polymorphic_iarchive_route(){}; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_POLYMORPHIC_IARCHIVE_DISPATCH_HPP
diff --git a/boost/boost/archive/detail/polymorphic_oarchive_route.hpp b/boost/boost/archive/detail/polymorphic_oarchive_route.hpp new file mode 100644 index 0000000..9211df2 --- /dev/null +++ b/boost/boost/archive/detail/polymorphic_oarchive_route.hpp
@@ -0,0 +1,205 @@ +#ifndef BOOST_ARCHIVE_DETAIL_POLYMORPHIC_OARCHIVE_ROUTE_HPP +#define BOOST_ARCHIVE_DETAIL_POLYMORPHIC_OARCHIVE_ROUTE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_oarchive_route.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <string> +#include <ostream> +#include <cstddef> // size_t + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/cstdint.hpp> +#include <boost/integer_traits.hpp> +#include <boost/archive/polymorphic_oarchive.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization +namespace archive { +namespace detail{ + +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer; +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer; + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +template<class ArchiveImplementation> +class polymorphic_oarchive_route : + public polymorphic_oarchive, + // note: gcc dynamic cross cast fails if the the derivation below is + // not public. I think this is a mistake. + public /*protected*/ ArchiveImplementation +{ +private: + // these are used by the serialization library. + virtual void save_object( + const void *x, + const detail::basic_oserializer & bos + ){ + ArchiveImplementation::save_object(x, bos); + } + virtual void save_pointer( + const void * t, + const detail::basic_pointer_oserializer * bpos_ptr + ){ + ArchiveImplementation::save_pointer(t, bpos_ptr); + } + virtual void save_null_pointer(){ + ArchiveImplementation::save_null_pointer(); + } + // primitive types the only ones permitted by polymorphic archives + virtual void save(const bool t){ + ArchiveImplementation::save(t); + } + virtual void save(const char t){ + ArchiveImplementation::save(t); + } + virtual void save(const signed char t){ + ArchiveImplementation::save(t); + } + virtual void save(const unsigned char t){ + ArchiveImplementation::save(t); + } + #ifndef BOOST_NO_CWCHAR + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + virtual void save(const wchar_t t){ + ArchiveImplementation::save(t); + } + #endif + #endif + virtual void save(const short t){ + ArchiveImplementation::save(t); + } + virtual void save(const unsigned short t){ + ArchiveImplementation::save(t); + } + virtual void save(const int t){ + ArchiveImplementation::save(t); + } + virtual void save(const unsigned int t){ + ArchiveImplementation::save(t); + } + virtual void save(const long t){ + ArchiveImplementation::save(t); + } + virtual void save(const unsigned long t){ + ArchiveImplementation::save(t); + } + #if defined(BOOST_HAS_LONG_LONG) + virtual void save(const boost::long_long_type t){ + ArchiveImplementation::save(t); + } + virtual void save(const boost::ulong_long_type t){ + ArchiveImplementation::save(t); + } + #elif defined(BOOST_HAS_MS_INT64) + virtual void save(const boost::int64_t t){ + ArchiveImplementation::save(t); + } + virtual void save(const boost::uint64_t t){ + ArchiveImplementation::save(t); + } + #endif + virtual void save(const float t){ + ArchiveImplementation::save(t); + } + virtual void save(const double t){ + ArchiveImplementation::save(t); + } + virtual void save(const std::string & t){ + ArchiveImplementation::save(t); + } + #ifndef BOOST_NO_STD_WSTRING + virtual void save(const std::wstring & t){ + ArchiveImplementation::save(t); + } + #endif + virtual library_version_type get_library_version() const{ + return ArchiveImplementation::get_library_version(); + } + virtual unsigned int get_flags() const { + return ArchiveImplementation::get_flags(); + } + virtual void save_binary(const void * t, std::size_t size){ + ArchiveImplementation::save_binary(t, size); + } + // used for xml and other tagged formats default does nothing + virtual void save_start(const char * name){ + ArchiveImplementation::save_start(name); + } + virtual void save_end(const char * name){ + ArchiveImplementation::save_end(name); + } + virtual void end_preamble(){ + ArchiveImplementation::end_preamble(); + } + virtual void register_basic_serializer(const detail::basic_oserializer & bos){ + ArchiveImplementation::register_basic_serializer(bos); + } +public: + // this can't be inheriteded because they appear in mulitple + // parents + typedef mpl::bool_<false> is_loading; + typedef mpl::bool_<true> is_saving; + // the << operator + template<class T> + polymorphic_oarchive & operator<<(T & t){ + return polymorphic_oarchive::operator<<(t); + } + // the & operator + template<class T> + polymorphic_oarchive & operator&(T & t){ + return polymorphic_oarchive::operator&(t); + } + // register type function + template<class T> + const basic_pointer_oserializer * + register_type(T * t = NULL){ + return ArchiveImplementation::register_type(t); + } + // all current archives take a stream as constructor argument + template <class _Elem, class _Tr> + polymorphic_oarchive_route( + std::basic_ostream<_Elem, _Tr> & os, + unsigned int flags = 0 + ) : + ArchiveImplementation(os, flags) + {} + virtual ~polymorphic_oarchive_route(){}; +}; + +} // namespace detail +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_DETAIL_POLYMORPHIC_OARCHIVE_DISPATCH_HPP
diff --git a/boost/boost/archive/detail/register_archive.hpp b/boost/boost/archive/detail/register_archive.hpp new file mode 100644 index 0000000..5ffecc7 --- /dev/null +++ b/boost/boost/archive/detail/register_archive.hpp
@@ -0,0 +1,91 @@ +// Copyright David Abrahams 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_ARCHIVE_DETAIL_REGISTER_ARCHIVE_DWA2006521_HPP +# define BOOST_ARCHIVE_DETAIL_REGISTER_ARCHIVE_DWA2006521_HPP + +namespace boost { namespace archive { namespace detail { + +// No instantiate_ptr_serialization overloads generated by +// BOOST_SERIALIZATION_REGISTER_ARCHIVE that lexically follow the call +// will be seen *unless* they are in an associated namespace of one of +// the arguments, so we pass one of these along to make sure this +// namespace is considered. See temp.dep.candidate (14.6.4.2) in the +// standard. +struct adl_tag {}; + +template <class Archive, class Serializable> +struct ptr_serialization_support; + +// We could've just used ptr_serialization_support, above, but using +// it with only a forward declaration causes vc6/7 to complain about a +// missing instantiate member, even if it has one. This is just a +// friendly layer of indirection. +template <class Archive, class Serializable> +struct _ptr_serialization_support + : ptr_serialization_support<Archive,Serializable> +{ + typedef int type; +}; + +#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5130) + +template<int N> +struct counter : counter<N-1> {}; +template<> +struct counter<0> {}; + +template<class Serializable> +void instantiate_ptr_serialization(Serializable* s, int, adl_tag) { + instantiate_ptr_serialization(s, counter<20>()); +} + +template<class Archive> +struct get_counter { + static const int value = sizeof(adjust_counter(counter<20>())); + typedef counter<value> type; + typedef counter<value - 1> prior; + typedef char (&next)[value+1]; +}; + +char adjust_counter(counter<0>); +template<class Serializable> +void instantiate_ptr_serialization(Serializable*, counter<0>) {} + +#define BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive) \ +namespace boost { namespace archive { namespace detail { \ + get_counter<Archive >::next adjust_counter(get_counter<Archive >::type);\ + template<class Serializable> \ + void instantiate_ptr_serialization(Serializable* s, \ + get_counter<Archive >::type) { \ + ptr_serialization_support<Archive, Serializable> x; \ + instantiate_ptr_serialization(s, get_counter<Archive >::prior()); \ + }\ +}}} + + +#else + +// This function gets called, but its only purpose is to participate +// in overload resolution with the functions declared by +// BOOST_SERIALIZATION_REGISTER_ARCHIVE, below. +template <class Serializable> +void instantiate_ptr_serialization(Serializable*, int, adl_tag ) {} + +// The function declaration generated by this macro never actually +// gets called, but its return type gets instantiated, and that's +// enough to cause registration of serialization functions between +// Archive and any exported Serializable type. See also: +// boost/serialization/export.hpp +# define BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive) \ +namespace boost { namespace archive { namespace detail { \ + \ +template <class Serializable> \ +typename _ptr_serialization_support<Archive, Serializable>::type \ +instantiate_ptr_serialization( Serializable*, Archive*, adl_tag ); \ + \ +}}} +#endif +}}} // namespace boost::archive::detail + +#endif // BOOST_ARCHIVE_DETAIL_INSTANTIATE_SERIALIZE_DWA2006521_HPP
diff --git a/boost/boost/archive/detail/utf8_codecvt_facet.hpp b/boost/boost/archive/detail/utf8_codecvt_facet.hpp new file mode 100644 index 0000000..b2430d5 --- /dev/null +++ b/boost/boost/archive/detail/utf8_codecvt_facet.hpp
@@ -0,0 +1,23 @@ +// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia@osl.iu.edu) +// Andrew Lumsdaine, Indiana University (lums@osl.iu.edu). +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP +#define BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP + +#ifdef BOOST_NO_CXX11_HDR_CODECVT + #define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { namespace archive { namespace detail { + #define BOOST_UTF8_DECL + #define BOOST_UTF8_END_NAMESPACE }}} + + #include <boost/detail/utf8_codecvt_facet.hpp> + + #undef BOOST_UTF8_END_NAMESPACE + #undef BOOST_UTF8_DECL + #undef BOOST_UTF8_BEGIN_NAMESPACE +#endif // BOOST_NO_CXX11_HDR_CODECVT +#endif // BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP +
diff --git a/boost/boost/archive/dinkumware.hpp b/boost/boost/archive/dinkumware.hpp new file mode 100644 index 0000000..90ba627 --- /dev/null +++ b/boost/boost/archive/dinkumware.hpp
@@ -0,0 +1,224 @@ +#ifndef BOOST_ARCHIVE_DINKUMWARE_HPP +#define BOOST_ARCHIVE_DINKUMWARE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// dinkumware.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// this file adds a couple of things that are missing from the dinkumware +// implementation of the standard library. + +#include <iterator> +#include <string> + +#include <boost/config.hpp> +#include <boost/cstdint.hpp> + +namespace std { + +// define i/o operators for 64 bit integers +template<class CharType> +basic_ostream<CharType> & +operator<<(basic_ostream<CharType> & os, boost::uint64_t t){ + // octal rendering of 64 bit number would be 22 octets + eos + CharType d[23]; + unsigned int radix; + + if(os.flags() & (int)std::ios_base::hex) + radix = 16; + else + if(os.flags() & (int)std::ios_base::oct) + radix = 8; + else + //if(s.flags() & (int)std::ios_base::dec) + radix = 10; + unsigned int i = 0; + do{ + unsigned int j = t % radix; + d[i++] = j + ((j < 10) ? '0' : ('a' - 10)); + t /= radix; + } + while(t > 0); + d[i--] = '\0'; + + // reverse digits + unsigned int j = 0; + while(j < i){ + CharType k = d[i]; + d[i] = d[j]; + d[j] = k; + --i;++j; + } + os << d; + return os; + +} + +template<class CharType> +basic_ostream<CharType> & +operator<<(basic_ostream<CharType> &os, boost::int64_t t){ + if(0 <= t){ + os << static_cast<boost::uint64_t>(t); + } + else{ + os.put('-'); + os << -t; + } + return os; +} + +template<class CharType> +basic_istream<CharType> & +operator>>(basic_istream<CharType> &is, boost::int64_t & t){ + CharType d; + do{ + d = is.get(); + } + while(::isspace(d)); + bool negative = (d == '-'); + if(negative) + d = is.get(); + unsigned int radix; + if(is.flags() & (int)std::ios_base::hex) + radix = 16; + else + if(is.flags() & (int)std::ios_base::oct) + radix = 8; + else + //if(s.flags() & (int)std::ios_base::dec) + radix = 10; + t = 0; + do{ + if('0' <= d && d <= '9') + t = t * radix + (d - '0'); + else + if('a' <= d && d <= 'f') + t = t * radix + (d - 'a' + 10); + else + break; + d = is.get(); + } + while(!is.fail()); + // restore the delimiter + is.putback(d); + is.clear(); + if(negative) + t = -t; + return is; +} + +template<class CharType> +basic_istream<CharType> & +operator>>(basic_istream<CharType> &is, boost::uint64_t & t){ + boost::int64_t it; + is >> it; + t = it; + return is; +} + +//#endif + +template<> +class back_insert_iterator<basic_string<char> > : public + iterator<output_iterator_tag, char> +{ +public: + typedef basic_string<char> container_type; + typedef container_type::reference reference; + + explicit back_insert_iterator(container_type & s) + : container(& s) + {} // construct with container + + back_insert_iterator<container_type> & operator=( + container_type::const_reference Val_ + ){ // push value into container + //container->push_back(Val_); + *container += Val_; + return (*this); + } + + back_insert_iterator<container_type> & operator*(){ + return (*this); + } + + back_insert_iterator<container_type> & operator++(){ + // pretend to preincrement + return (*this); + } + + back_insert_iterator<container_type> operator++(int){ + // pretend to postincrement + return (*this); + } + +protected: + container_type *container; // pointer to container +}; + +template<char> +inline back_insert_iterator<basic_string<char> > back_inserter( + basic_string<char> & s +){ + return (std::back_insert_iterator<basic_string<char> >(s)); +} + +template<> +class back_insert_iterator<basic_string<wchar_t> > : public + iterator<output_iterator_tag, wchar_t> +{ +public: + typedef basic_string<wchar_t> container_type; + typedef container_type::reference reference; + + explicit back_insert_iterator(container_type & s) + : container(& s) + {} // construct with container + + back_insert_iterator<container_type> & operator=( + container_type::const_reference Val_ + ){ // push value into container + //container->push_back(Val_); + *container += Val_; + return (*this); + } + + back_insert_iterator<container_type> & operator*(){ + return (*this); + } + + back_insert_iterator<container_type> & operator++(){ + // pretend to preincrement + return (*this); + } + + back_insert_iterator<container_type> operator++(int){ + // pretend to postincrement + return (*this); + } + +protected: + container_type *container; // pointer to container +}; + +template<wchar_t> +inline back_insert_iterator<basic_string<wchar_t> > back_inserter( + basic_string<wchar_t> & s +){ + return (std::back_insert_iterator<basic_string<wchar_t> >(s)); +} + +} // namespace std + +#endif //BOOST_ARCHIVE_DINKUMWARE_HPP
diff --git a/boost/boost/archive/impl/archive_serializer_map.ipp b/boost/boost/archive/impl/archive_serializer_map.ipp new file mode 100644 index 0000000..c8ad96b --- /dev/null +++ b/boost/boost/archive/impl/archive_serializer_map.ipp
@@ -0,0 +1,71 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// archive_serializer_map.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +////////////////////////////////////////////////////////////////////// +// implementation of basic_text_iprimitive overrides for the combination +// of template parameters used to implement a text_iprimitive + +#include <boost/config.hpp> +#include <boost/archive/detail/archive_serializer_map.hpp> +#include <boost/archive/detail/basic_serializer_map.hpp> +#include <boost/serialization/singleton.hpp> + +namespace boost { +namespace archive { +namespace detail { + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace extra_detail { // anon + template<class Archive> + class map : public basic_serializer_map + {}; +} + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(bool) +archive_serializer_map<Archive>::insert(const basic_serializer * bs){ + return boost::serialization::singleton< + extra_detail::map<Archive> + >::get_mutable_instance().insert(bs); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +archive_serializer_map<Archive>::erase(const basic_serializer * bs){ + if(boost::serialization::singleton< + extra_detail::map<Archive> + >::is_destroyed()) + return; + boost::serialization::singleton< + extra_detail::map<Archive> + >::get_mutable_instance().erase(bs); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(const basic_serializer *) +archive_serializer_map<Archive>::find( + const boost::serialization::extended_type_info & eti +) { + return boost::serialization::singleton< + extra_detail::map<Archive> + >::get_const_instance().find(eti); +} + +} // namespace detail +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/basic_binary_iarchive.ipp b/boost/boost/archive/impl/basic_binary_iarchive.ipp new file mode 100644 index 0000000..5067b09 --- /dev/null +++ b/boost/boost/archive/impl/basic_binary_iarchive.ipp
@@ -0,0 +1,134 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_iarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. +#include <string> +#include <boost/assert.hpp> +#include <algorithm> +#include <cstring> + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; + using ::strlen; + using ::size_t; +} +#endif + +#include <boost/detail/workaround.hpp> +#include <boost/detail/endian.hpp> + +#include <boost/archive/basic_binary_iarchive.hpp> + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of binary_binary_archive +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iarchive<Archive>::load_override(class_name_type & t, int){ + std::string cn; + cn.reserve(BOOST_SERIALIZATION_MAX_KEY_SIZE); + load_override(cn, 0); + if(cn.size() > (BOOST_SERIALIZATION_MAX_KEY_SIZE - 1)) + boost::serialization::throw_exception( + archive_exception(archive_exception::invalid_class_name) + ); + std::memcpy(t, cn.data(), cn.size()); + // borland tweak + t.t[cn.size()] = '\0'; +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iarchive<Archive>::init(){ + // read signature in an archive version independent manner + std::string file_signature; + + #if 0 // commented out since it interfers with derivation + BOOST_TRY { + std::size_t l; + this->This()->load(l); + if(l == std::strlen(BOOST_ARCHIVE_SIGNATURE())) { + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != file_signature.data()) + #endif + file_signature.resize(l); + // note breaking a rule here - could be a problem on some platform + if(0 < l) + this->This()->load_binary(&(*file_signature.begin()), l); + } + } + BOOST_CATCH(archive_exception const &) { // catch stream_error archive exceptions + // will cause invalid_signature archive exception to be thrown below + file_signature = ""; + } + BOOST_CATCH_END + #else + // https://svn.boost.org/trac/boost/ticket/7301 + * this->This() >> file_signature; + #endif + + if(file_signature != BOOST_ARCHIVE_SIGNATURE()) + boost::serialization::throw_exception( + archive_exception(archive_exception::invalid_signature) + ); + + // make sure the version of the reading archive library can + // support the format of the archive being read + library_version_type input_library_version; + //* this->This() >> input_library_version; + { + int v = 0; + v = this->This()->m_sb.sbumpc(); + #if defined(BOOST_LITTLE_ENDIAN) + if(v < 6){ + ; + } + else + if(v < 7){ + // version 6 - next byte should be zero + this->This()->m_sb.sbumpc(); + } + else + if(v < 8){ + int x1; + // version 7 = might be followed by zero or some other byte + x1 = this->This()->m_sb.sgetc(); + // it's =a zero, push it back + if(0 == x1) + this->This()->m_sb.sbumpc(); + } + else{ + // version 8+ followed by a zero + this->This()->m_sb.sbumpc(); + } + #elif defined(BOOST_BIG_ENDIAN) + if(v == 0) + v = this->This()->m_sb.sbumpc(); + #endif + input_library_version = static_cast<library_version_type>(v); + } + + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + this->set_library_version(input_library_version); + #else + detail::basic_iarchive::set_library_version(input_library_version); + #endif + + if(BOOST_ARCHIVE_VERSION() < input_library_version) + boost::serialization::throw_exception( + archive_exception(archive_exception::unsupported_version) + ); +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/basic_binary_iprimitive.ipp b/boost/boost/archive/impl/basic_binary_iprimitive.ipp new file mode 100644 index 0000000..e22c3bd --- /dev/null +++ b/boost/boost/archive/impl/basic_binary_iprimitive.ipp
@@ -0,0 +1,210 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_iprimitive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> +#include <cstddef> // size_t, NULL +#include <cstring> // memcpy + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; + using ::memcpy; +} // namespace std +#endif + +#include <boost/detail/workaround.hpp> // fixup for RogueWave + +#include <boost/serialization/throw_exception.hpp> + +#include <boost/core/no_exceptions_support.hpp> +#include <boost/archive/archive_exception.hpp> +#include <boost/archive/codecvt_null.hpp> +#include <boost/archive/add_facet.hpp> +#include <boost/archive/basic_binary_iprimitive.hpp> + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of basic_binary_iprimitive + +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive<Archive, Elem, Tr>::init() +{ + // Detect attempts to pass native binary archives across + // incompatible platforms. This is not fool proof but its + // better than nothing. + unsigned char size; + this->This()->load(size); + if(sizeof(int) != size) + boost::serialization::throw_exception( + archive_exception( + archive_exception::incompatible_native_format, + "size of int" + ) + ); + this->This()->load(size); + if(sizeof(long) != size) + boost::serialization::throw_exception( + archive_exception( + archive_exception::incompatible_native_format, + "size of long" + ) + ); + this->This()->load(size); + if(sizeof(float) != size) + boost::serialization::throw_exception( + archive_exception( + archive_exception::incompatible_native_format, + "size of float" + ) + ); + this->This()->load(size); + if(sizeof(double) != size) + boost::serialization::throw_exception( + archive_exception( + archive_exception::incompatible_native_format, + "size of double" + ) + ); + + // for checking endian + int i; + this->This()->load(i); + if(1 != i) + boost::serialization::throw_exception( + archive_exception( + archive_exception::incompatible_native_format, + "endian setting" + ) + ); +} + +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive<Archive, Elem, Tr>::load(wchar_t * ws) +{ + std::size_t l; // number of wchar_t !!! + this->This()->load(l); + load_binary(ws, l * sizeof(wchar_t) / sizeof(char)); + ws[l] = L'\0'; +} + +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive<Archive, Elem, Tr>::load(std::string & s) +{ + std::size_t l; + this->This()->load(l); + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != s.data()) + #endif + s.resize(l); + // note breaking a rule here - could be a problem on some platform + if(0 < l) + load_binary(&(*s.begin()), l); +} + +#ifndef BOOST_NO_CWCHAR +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive<Archive, Elem, Tr>::load(char * s) +{ + std::size_t l; + this->This()->load(l); + load_binary(s, l); + s[l] = '\0'; +} +#endif + +#ifndef BOOST_NO_STD_WSTRING +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_iprimitive<Archive, Elem, Tr>::load(std::wstring & ws) +{ + std::size_t l; + this->This()->load(l); + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != ws.data()) + #endif + ws.resize(l); + // note breaking a rule here - is could be a problem on some platform + load_binary(const_cast<wchar_t *>(ws.data()), l * sizeof(wchar_t) / sizeof(char)); +} +#endif + +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_binary_iprimitive<Archive, Elem, Tr>::basic_binary_iprimitive( + std::basic_streambuf<Elem, Tr> & sb, + bool no_codecvt +) : +#ifndef BOOST_NO_STD_LOCALE + m_sb(sb), + locale_saver(m_sb) +{ + if(! no_codecvt){ + archive_locale.reset( + add_facet( + std::locale::classic(), + new codecvt_null<Elem> + ) + ); + //m_sb.pubimbue(* archive_locale); + } +} +#else + m_sb(sb) +{} +#endif + +// some libraries including stl and libcomo fail if the +// buffer isn't flushed before the code_cvt facet is changed. +// I think this is a bug. We explicity invoke sync to when +// we're done with the streambuf to work around this problem. +// Note that sync is a protected member of stream buff so we +// have to invoke it through a contrived derived class. +namespace detail { +// note: use "using" to get past msvc bug +using namespace std; +template<class Elem, class Tr> +class input_streambuf_access : public std::basic_streambuf<Elem, Tr> { + public: + virtual int sync(){ +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) + return this->basic_streambuf::sync(); +#else + return this->basic_streambuf<Elem, Tr>::sync(); +#endif + } +}; +} // detail + +// scoped_ptr requires that archive_locale be a complete type at time of +// destruction so define destructor here rather than in the header +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_binary_iprimitive<Archive, Elem, Tr>::~basic_binary_iprimitive(){ + // push back unread characters + //destructor can't throw ! + BOOST_TRY{ + static_cast<detail::input_streambuf_access<Elem, Tr> &>(m_sb).sync(); + } + BOOST_CATCH(...){ + } + BOOST_CATCH_END +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/basic_binary_oarchive.ipp b/boost/boost/archive/impl/basic_binary_oarchive.ipp new file mode 100644 index 0000000..467fd6f --- /dev/null +++ b/boost/boost/archive/impl/basic_binary_oarchive.ipp
@@ -0,0 +1,46 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_oarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. +#include <string> +#include <boost/assert.hpp> +#include <algorithm> +#include <cstring> + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} +#endif + +#include <boost/archive/basic_binary_oarchive.hpp> + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of binary_binary_oarchive + +template<class Archive> +#if !defined(__BORLANDC__) +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +#else +void +#endif +basic_binary_oarchive<Archive>::init(){ + // write signature in an archive version independent manner + const std::string file_signature(BOOST_ARCHIVE_SIGNATURE()); + * this->This() << file_signature; + // write library version + const library_version_type v(BOOST_ARCHIVE_VERSION()); + * this->This() << v; +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/basic_binary_oprimitive.ipp b/boost/boost/archive/impl/basic_binary_oprimitive.ipp new file mode 100644 index 0000000..238617d --- /dev/null +++ b/boost/boost/archive/impl/basic_binary_oprimitive.ipp
@@ -0,0 +1,162 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_binary_oprimitive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <ostream> +#include <cstddef> // NULL +#include <cstring> + +#include <boost/config.hpp> + +#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__) +namespace std{ + using ::strlen; +} // namespace std +#endif + +#ifndef BOOST_NO_CWCHAR +#include <cwchar> +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::wcslen; } +#endif +#endif + +#include <boost/detail/workaround.hpp> + +#include <boost/archive/add_facet.hpp> +#include <boost/archive/codecvt_null.hpp> +#include <boost/archive/basic_binary_oprimitive.hpp> +#include <boost/core/no_exceptions_support.hpp> + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of basic_binary_oprimitive + +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive<Archive, Elem, Tr>::init() +{ + // record native sizes of fundamental types + // this is to permit detection of attempts to pass + // native binary archives accross incompatible machines. + // This is not foolproof but its better than nothing. + this->This()->save(static_cast<unsigned char>(sizeof(int))); + this->This()->save(static_cast<unsigned char>(sizeof(long))); + this->This()->save(static_cast<unsigned char>(sizeof(float))); + this->This()->save(static_cast<unsigned char>(sizeof(double))); + // for checking endianness + this->This()->save(int(1)); +} + +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive<Archive, Elem, Tr>::save(const char * s) +{ + std::size_t l = std::strlen(s); + this->This()->save(l); + save_binary(s, l); +} + +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::string &s) +{ + std::size_t l = static_cast<std::size_t>(s.size()); + this->This()->save(l); + save_binary(s.data(), l); +} + +#ifndef BOOST_NO_CWCHAR +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive<Archive, Elem, Tr>::save(const wchar_t * ws) +{ + std::size_t l = std::wcslen(ws); + this->This()->save(l); + save_binary(ws, l * sizeof(wchar_t) / sizeof(char)); +} +#endif + +#ifndef BOOST_NO_STD_WSTRING +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::wstring &ws) +{ + std::size_t l = ws.size(); + this->This()->save(l); + save_binary(ws.data(), l * sizeof(wchar_t) / sizeof(char)); +} +#endif + +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_binary_oprimitive<Archive, Elem, Tr>::basic_binary_oprimitive( + std::basic_streambuf<Elem, Tr> & sb, + bool no_codecvt +) : +#ifndef BOOST_NO_STD_LOCALE + m_sb(sb), + locale_saver(m_sb) +{ + if(! no_codecvt){ + archive_locale.reset( + add_facet( + std::locale::classic(), + new codecvt_null<Elem> + ) + ); + //m_sb.pubimbue(* archive_locale); + } +} +#else + m_sb(sb) +{} +#endif + +// some libraries including stl and libcomo fail if the +// buffer isn't flushed before the code_cvt facet is changed. +// I think this is a bug. We explicity invoke sync to when +// we're done with the streambuf to work around this problem. +// Note that sync is a protected member of stream buff so we +// have to invoke it through a contrived derived class. +namespace detail { +// note: use "using" to get past msvc bug +using namespace std; +template<class Elem, class Tr> +class output_streambuf_access : public std::basic_streambuf<Elem, Tr> { + public: + virtual int sync(){ +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206)) + return this->basic_streambuf::sync(); +#else + return this->basic_streambuf<Elem, Tr>::sync(); +#endif + } +}; +} // detail + +// scoped_ptr requires that g be a complete type at time of +// destruction so define destructor here rather than in the header +template<class Archive, class Elem, class Tr> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_binary_oprimitive<Archive, Elem, Tr>::~basic_binary_oprimitive(){ + // flush buffer + //destructor can't throw + BOOST_TRY{ + static_cast<detail::output_streambuf_access<Elem, Tr> &>(m_sb).sync(); + } + BOOST_CATCH(...){ + } + BOOST_CATCH_END +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/basic_text_iarchive.ipp b/boost/boost/archive/impl/basic_text_iarchive.ipp new file mode 100644 index 0000000..8d364f9 --- /dev/null +++ b/boost/boost/archive/impl/basic_text_iarchive.ipp
@@ -0,0 +1,76 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_iarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. +#include <string> +#include <algorithm> +#include <cstring> + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} +#endif + +#include <boost/detail/workaround.hpp> +#include <boost/serialization/string.hpp> +#include <boost/archive/basic_text_iarchive.hpp> + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of text_text_archive + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_iarchive<Archive>::load_override(class_name_type & t, int){ + std::string cn; + cn.reserve(BOOST_SERIALIZATION_MAX_KEY_SIZE); + load_override(cn, 0); + if(cn.size() > (BOOST_SERIALIZATION_MAX_KEY_SIZE - 1)) + boost::serialization::throw_exception( + archive_exception(archive_exception::invalid_class_name) + ); + std::memcpy(t, cn.data(), cn.size()); + // borland tweak + t.t[cn.size()] = '\0'; +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_iarchive<Archive>::init(void){ + // read signature in an archive version independent manner + std::string file_signature; + * this->This() >> file_signature; + if(file_signature != BOOST_ARCHIVE_SIGNATURE()) + boost::serialization::throw_exception( + archive_exception(archive_exception::invalid_signature) + ); + + // make sure the version of the reading archive library can + // support the format of the archive being read + library_version_type input_library_version; + * this->This() >> input_library_version; + + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + this->set_library_version(input_library_version); + #else + detail::basic_iarchive::set_library_version(input_library_version); + #endif + + // extra little .t is to get around borland quirk + if(BOOST_ARCHIVE_VERSION() < input_library_version) + boost::serialization::throw_exception( + archive_exception(archive_exception::unsupported_version) + ); +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/basic_text_iprimitive.ipp b/boost/boost/archive/impl/basic_text_iprimitive.ipp new file mode 100644 index 0000000..9b66789 --- /dev/null +++ b/boost/boost/archive/impl/basic_text_iprimitive.ipp
@@ -0,0 +1,151 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_iprimitive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstddef> // size_t +#include <cstddef> // NULL + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/serialization/throw_exception.hpp> +#include <boost/serialization/pfto.hpp> + +#include <boost/archive/basic_text_iprimitive.hpp> +#include <boost/archive/codecvt_null.hpp> +#include <boost/archive/add_facet.hpp> + +#include <boost/archive/iterators/remove_whitespace.hpp> +#include <boost/archive/iterators/istream_iterator.hpp> +#include <boost/archive/iterators/binary_from_base64.hpp> +#include <boost/archive/iterators/transform_width.hpp> + +namespace boost { +namespace archive { + +namespace detail { + template<class CharType> + static inline bool is_whitespace(CharType c); + + template<> + inline bool is_whitespace(char t){ + return 0 != std::isspace(t); + } + + #ifndef BOOST_NO_CWCHAR + template<> + inline bool is_whitespace(wchar_t t){ + return 0 != std::iswspace(t); + } + #endif +} // detail + +// translate base64 text into binary and copy into buffer +// until buffer is full. +template<class IStream> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_iprimitive<IStream>::load_binary( + void *address, + std::size_t count +){ + typedef typename IStream::char_type CharType; + + if(0 == count) + return; + + BOOST_ASSERT( + static_cast<std::size_t>((std::numeric_limits<std::streamsize>::max)()) + > (count + sizeof(CharType) - 1)/sizeof(CharType) + ); + + if(is.fail()) + boost::serialization::throw_exception( + archive_exception(archive_exception::input_stream_error) + ); + // convert from base64 to binary + typedef typename + iterators::transform_width< + iterators::binary_from_base64< + iterators::remove_whitespace< + iterators::istream_iterator<CharType> + > + ,CharType + > + ,8 + ,6 + ,CharType + > + 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>(*i++); + } + + // skip over any excess input + for(;;){ + typename IStream::int_type r; + r = is.get(); + if(is.eof()) + break; + if(detail::is_whitespace(static_cast<CharType>(r))) + break; + } +} + +template<class IStream> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_text_iprimitive<IStream>::basic_text_iprimitive( + IStream &is_, + bool no_codecvt +) : +#ifndef BOOST_NO_STD_LOCALE + is(is_), + flags_saver(is_), + precision_saver(is_), + locale_saver(* is_.rdbuf()) +{ + if(! no_codecvt){ + archive_locale.reset( + add_facet( + std::locale::classic(), + new boost::archive::codecvt_null<typename IStream::char_type> + ) + ); + //is.imbue(* archive_locale); + } + is >> std::noboolalpha; +} +#else + is(is_), + flags_saver(is_), + precision_saver(is_) +{} +#endif + +template<class IStream> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_text_iprimitive<IStream>::~basic_text_iprimitive(){ + is.sync(); +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/basic_text_oarchive.ipp b/boost/boost/archive/impl/basic_text_oarchive.ipp new file mode 100644 index 0000000..4170c97 --- /dev/null +++ b/boost/boost/archive/impl/basic_text_oarchive.ipp
@@ -0,0 +1,62 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_oarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. +#include <string> +#include <boost/assert.hpp> +#include <cstring> + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} +#endif + +#include <boost/archive/basic_text_oarchive.hpp> + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of basic_text_oarchive + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_oarchive<Archive>::newtoken() +{ + switch(delimiter){ + default: + BOOST_ASSERT(false); + break; + case eol: + this->This()->put('\n'); + delimiter = space; + break; + case space: + this->This()->put(' '); + break; + case none: + delimiter = space; + break; + } +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_oarchive<Archive>::init(){ + // write signature in an archive version independent manner + const std::string file_signature(BOOST_ARCHIVE_SIGNATURE()); + * this->This() << file_signature; + // write library version + const library_version_type v(BOOST_ARCHIVE_VERSION()); + * this->This() << v; +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/basic_text_oprimitive.ipp b/boost/boost/archive/impl/basic_text_oprimitive.ipp new file mode 100644 index 0000000..10e2133 --- /dev/null +++ b/boost/boost/archive/impl/basic_text_oprimitive.ipp
@@ -0,0 +1,114 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_text_oprimitive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstddef> // NULL +#include <algorithm> // std::copy +#include <boost/serialization/pfto.hpp> + +#include <boost/archive/basic_text_oprimitive.hpp> +#include <boost/archive/codecvt_null.hpp> +#include <boost/archive/add_facet.hpp> + +#include <boost/archive/iterators/base64_from_binary.hpp> +#include <boost/archive/iterators/insert_linebreaks.hpp> +#include <boost/archive/iterators/transform_width.hpp> +#include <boost/archive/iterators/ostream_iterator.hpp> + +namespace boost { +namespace archive { + +// translate to base64 and copy in to buffer. +template<class OStream> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_text_oprimitive<OStream>::save_binary( + const void *address, + std::size_t count +){ + typedef typename OStream::char_type CharType; + + if(0 == count) + return; + + if(os.fail()) + boost::serialization::throw_exception( + archive_exception(archive_exception::output_stream_error) + ); + + os.put('\n'); + + typedef + boost::archive::iterators::insert_linebreaks< + boost::archive::iterators::base64_from_binary< + boost::archive::iterators::transform_width< + const char *, + 6, + 8 + > + > + ,76 + ,const char // cwpro8 needs this + > + base64_text; + + boost::archive::iterators::ostream_iterator<CharType> oi(os); + std::copy( + base64_text(BOOST_MAKE_PFTO_WRAPPER(static_cast<const char *>(address))), + base64_text( + BOOST_MAKE_PFTO_WRAPPER(static_cast<const char *>(address) + count) + ), + oi + ); + + std::size_t tail = count % 3; + if(tail > 0){ + *oi++ = '='; + if(tail < 2) + *oi = '='; + } +} + +template<class OStream> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_text_oprimitive<OStream>::basic_text_oprimitive( + OStream & os_, + bool no_codecvt +) : +#ifndef BOOST_NO_STD_LOCALE + os(os_), + flags_saver(os_), + precision_saver(os_), + locale_saver(* os_.rdbuf()) +{ + if(! no_codecvt){ + archive_locale.reset( + add_facet( + std::locale::classic(), + new boost::archive::codecvt_null<typename OStream::char_type> + ) + ); + //os.imbue(* archive_locale); + } + os << std::noboolalpha; +} +#else + os(os_), + flags_saver(os_), + precision_saver(os_) +{} +#endif + +template<class OStream> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_text_oprimitive<OStream>::~basic_text_oprimitive(){ + os << std::endl; +} + +} //namespace boost +} //namespace archive
diff --git a/boost/boost/archive/impl/basic_xml_grammar.hpp b/boost/boost/archive/impl/basic_xml_grammar.hpp new file mode 100644 index 0000000..66ca1f0 --- /dev/null +++ b/boost/boost/archive/impl/basic_xml_grammar.hpp
@@ -0,0 +1,173 @@ +#ifndef BOOST_ARCHIVE_BASIC_XML_GRAMMAR_HPP +#define BOOST_ARCHIVE_BASIC_XML_GRAMMAR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_grammar.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// this module is derived from simplexml.cpp - an example shipped as part of +// the spirit parser. This example contains the following notice: +/*============================================================================= + simplexml.cpp + + Spirit V1.3 + URL: http://spirit.sourceforge.net/ + + Copyright (c) 2001, Daniel C. Nuffer + + This software is provided 'as-is', without any express or implied + warranty. In no event will the copyright holder be held liable for + any damages arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute + it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must + not claim that you wrote the original software. If you use this + software in a product, an acknowledgment in the product documentation + would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +=============================================================================*/ +#include <string> + +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> + +#include <boost/spirit/include/classic_rule.hpp> +#include <boost/spirit/include/classic_chset.hpp> + +#include <boost/archive/basic_archive.hpp> +#include <boost/serialization/tracking.hpp> +#include <boost/serialization/version.hpp> + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// XML grammar parsing + +template<class CharType> +class basic_xml_grammar { +public: + // The following is not necessary according to DR45, but at least + // one compiler (Compaq C++ 6.5 in strict_ansi mode) chokes otherwise. + struct return_values; + friend struct return_values; + +private: + typedef BOOST_DEDUCED_TYPENAME std::basic_istream<CharType> IStream; + typedef BOOST_DEDUCED_TYPENAME std::basic_string<CharType> StringType; + typedef BOOST_DEDUCED_TYPENAME boost::spirit::classic::chset<CharType> chset_t; + typedef BOOST_DEDUCED_TYPENAME boost::spirit::classic::chlit<CharType> chlit_t; + typedef BOOST_DEDUCED_TYPENAME boost::spirit::classic::scanner< + BOOST_DEDUCED_TYPENAME std::basic_string<CharType>::iterator + > scanner_t; + typedef BOOST_DEDUCED_TYPENAME boost::spirit::classic::rule<scanner_t> rule_t; + // Start grammar definition + rule_t + Reference, + Eq, + STag, + ETag, + LetterOrUnderscoreOrColon, + AttValue, + CharRef1, + CharRef2, + CharRef, + AmpRef, + LTRef, + GTRef, + AposRef, + QuoteRef, + CharData, + CharDataChars, + content, + AmpName, + LTName, + GTName, + ClassNameChar, + ClassName, + Name, + XMLDecl, + XMLDeclChars, + DocTypeDecl, + DocTypeDeclChars, + ClassIDAttribute, + ObjectIDAttribute, + ClassNameAttribute, + TrackingAttribute, + VersionAttribute, + UnusedAttribute, + Attribute, + SignatureAttribute, + SerializationWrapper, + NameHead, + NameTail, + AttributeList, + S; + + // XML Character classes + chset_t + BaseChar, + Ideographic, + Char, + Letter, + Digit, + CombiningChar, + Extender, + Sch, + NameChar; + + void init_chset(); + + bool my_parse( + IStream & is, + const rule_t &rule_, + const CharType delimiter = L'>' + ) const ; +public: + struct return_values { + StringType object_name; + StringType contents; + //class_id_type class_id; + int_least16_t class_id; + //object_id_type object_id; + uint_least32_t object_id; + //version_type version; + unsigned int version; + tracking_type tracking_level; + StringType class_name; + return_values() : + version(0), + tracking_level(false) + {} + } rv; + bool parse_start_tag(IStream & is) /*const*/; + bool parse_end_tag(IStream & is) const; + bool parse_string(IStream & is, StringType & s) /*const*/; + void init(IStream & is); + void windup(IStream & is); + basic_xml_grammar(); +}; + +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_BASIC_XML_GRAMMAR_HPP
diff --git a/boost/boost/archive/impl/basic_xml_iarchive.ipp b/boost/boost/archive/impl/basic_xml_iarchive.ipp new file mode 100644 index 0000000..52dfde1 --- /dev/null +++ b/boost/boost/archive/impl/basic_xml_iarchive.ipp
@@ -0,0 +1,114 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_iarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> +#include <cstddef> // NULL +#include <algorithm> + +#include <boost/serialization/throw_exception.hpp> +#include <boost/archive/xml_archive_exception.hpp> +#include <boost/archive/basic_xml_iarchive.hpp> +#include <boost/serialization/tracking.hpp> + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implementation of xml_text_archive + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive<Archive>::load_start(const char *name){ + // if there's no name + if(NULL == name) + return; + bool result = this->This()->gimpl->parse_start_tag(this->This()->get_is()); + if(true != result){ + boost::serialization::throw_exception( + archive_exception(archive_exception::input_stream_error) + ); + } + // don't check start tag at highest level + ++depth; + return; +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive<Archive>::load_end(const char *name){ + // if there's no name + if(NULL == name) + return; + bool result = this->This()->gimpl->parse_end_tag(this->This()->get_is()); + if(true != result){ + boost::serialization::throw_exception( + archive_exception(archive_exception::input_stream_error) + ); + } + + // don't check start tag at highest level + if(0 == --depth) + return; + + if(0 == (this->get_flags() & no_xml_tag_checking)){ + // double check that the tag matches what is expected - useful for debug + if(0 != name[this->This()->gimpl->rv.object_name.size()] + || ! std::equal( + this->This()->gimpl->rv.object_name.begin(), + this->This()->gimpl->rv.object_name.end(), + name + ) + ){ + boost::serialization::throw_exception( + xml_archive_exception( + xml_archive_exception::xml_archive_tag_mismatch, + name + ) + ); + } + } +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive<Archive>::load_override(object_id_type & t, int){ + t = object_id_type(this->This()->gimpl->rv.object_id); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive<Archive>::load_override(version_type & t, int){ + t = version_type(this->This()->gimpl->rv.version); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive<Archive>::load_override(class_id_type & t, int){ + t = class_id_type(this->This()->gimpl->rv.class_id); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_iarchive<Archive>::load_override(tracking_type & t, int){ + t = this->This()->gimpl->rv.tracking_level; +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_xml_iarchive<Archive>::basic_xml_iarchive(unsigned int flags) : + detail::common_iarchive<Archive>(flags), + depth(0) +{} +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_xml_iarchive<Archive>::~basic_xml_iarchive(){} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/basic_xml_oarchive.ipp b/boost/boost/archive/impl/basic_xml_oarchive.ipp new file mode 100644 index 0000000..0c57a12 --- /dev/null +++ b/boost/boost/archive/impl/basic_xml_oarchive.ipp
@@ -0,0 +1,275 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// basic_xml_oarchive.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <algorithm> +#include <cstddef> // NULL +#include <cstring> +#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__) +namespace std{ + using ::strlen; +} // namespace std +#endif + +#include <boost/archive/basic_xml_archive.hpp> +#include <boost/archive/basic_xml_oarchive.hpp> +#include <boost/archive/xml_archive_exception.hpp> +#include <boost/core/no_exceptions_support.hpp> + +namespace boost { +namespace archive { + +namespace detail { +template<class CharType> +struct XML_name { + void operator()(CharType t) const{ + const unsigned char lookup_table[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0, // -. + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, // 0-9 + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // A- + 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, // -Z _ + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // a- + 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, // -z + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; + if((unsigned)t > 127) + return; + if(0 == lookup_table[(unsigned)t]) + boost::serialization::throw_exception( + xml_archive_exception( + xml_archive_exception::xml_archive_tag_name_error + ) + ); + } +}; + +} // namespace detail + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions common to both types of xml output + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::write_attribute( + const char *attribute_name, + int t, + const char *conjunction +){ + this->This()->put(' '); + this->This()->put(attribute_name); + this->This()->put(conjunction); + this->This()->save(t); + this->This()->put('"'); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::write_attribute( + const char *attribute_name, + const char *key +){ + this->This()->put(' '); + this->This()->put(attribute_name); + this->This()->put("=\""); + this->This()->save(key); + this->This()->put('"'); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::indent(){ + int i; + for(i = depth; i-- > 0;) + this->This()->put('\t'); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_start(const char *name) +{ + if(NULL == name) + return; + + // be sure name has no invalid characters + std::for_each(name, name + std::strlen(name), detail::XML_name<const char>()); + + end_preamble(); + if(depth > 0){ + this->This()->put('\n'); + indent(); + } + ++depth; + this->This()->put('<'); + this->This()->save(name); + pending_preamble = true; + indent_next = false; +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_end(const char *name) +{ + if(NULL == name) + return; + + // be sure name has no invalid characters + std::for_each(name, name + std::strlen(name), detail::XML_name<const char>()); + + end_preamble(); + --depth; + if(indent_next){ + this->This()->put('\n'); + indent(); + } + indent_next = true; + this->This()->put("</"); + this->This()->save(name); + this->This()->put('>'); + if(0 == depth) + this->This()->put('\n'); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::end_preamble(){ + if(pending_preamble){ + this->This()->put('>'); + pending_preamble = false; + } +} +#if 0 +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override(const object_id_type & t, int) +{ + int i = t.t; // extra .t is for borland + write_attribute(BOOST_ARCHIVE_XML_OBJECT_ID(), i, "=\"_"); +} +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override( + const object_reference_type & t, + int +){ + int i = t.t; // extra .t is for borland + write_attribute(BOOST_ARCHIVE_XML_OBJECT_REFERENCE(), i, "=\"_"); +} +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override(const version_type & t, int) +{ + int i = t.t; // extra .t is for borland + write_attribute(BOOST_ARCHIVE_XML_VERSION(), i); +} +#endif + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override(const object_id_type & t, int) +{ + // borland doesn't do conversion of STRONG_TYPEDEFs very well + const unsigned int i = t; + write_attribute(BOOST_ARCHIVE_XML_OBJECT_ID(), i, "=\"_"); +} +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override( + const object_reference_type & t, + int +){ + const unsigned int i = t; + write_attribute(BOOST_ARCHIVE_XML_OBJECT_REFERENCE(), i, "=\"_"); +} +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override(const version_type & t, int) +{ + const unsigned int i = t; + write_attribute(BOOST_ARCHIVE_XML_VERSION(), i); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override(const class_id_type & t, int) +{ + write_attribute(BOOST_ARCHIVE_XML_CLASS_ID(), t); +} +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override( + const class_id_reference_type & t, + int +){ + write_attribute(BOOST_ARCHIVE_XML_CLASS_ID_REFERENCE(), t); +} +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override( + const class_id_optional_type & t, + int +){ + write_attribute(BOOST_ARCHIVE_XML_CLASS_ID(), t); +} +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override(const class_name_type & t, int) +{ + const char * key = t; + if(NULL == key) + return; + write_attribute(BOOST_ARCHIVE_XML_CLASS_NAME(), key); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::save_override(const tracking_type & t, int) +{ + write_attribute(BOOST_ARCHIVE_XML_TRACKING(), t.t); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) +basic_xml_oarchive<Archive>::init(){ + // xml header + this->This()->put("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"); + this->This()->put("<!DOCTYPE boost_serialization>\n"); + // xml document wrapper - outer root + this->This()->put("<boost_serialization"); + write_attribute("signature", BOOST_ARCHIVE_SIGNATURE()); + write_attribute("version", BOOST_ARCHIVE_VERSION()); + this->This()->put(">\n"); +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_xml_oarchive<Archive>::basic_xml_oarchive(unsigned int flags) : + detail::common_oarchive<Archive>(flags), + depth(0), + indent_next(false), + pending_preamble(false) +{ +} + +template<class Archive> +BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) +basic_xml_oarchive<Archive>::~basic_xml_oarchive(){ + if(0 == (this->get_flags() & no_header)){ + BOOST_TRY{ + this->This()->put("</boost_serialization>\n"); + } + BOOST_CATCH(...){} + BOOST_CATCH_END + } +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/text_iarchive_impl.ipp b/boost/boost/archive/impl/text_iarchive_impl.ipp new file mode 100644 index 0000000..f14c0d8 --- /dev/null +++ b/boost/boost/archive/impl/text_iarchive_impl.ipp
@@ -0,0 +1,128 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_iarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +////////////////////////////////////////////////////////////////////// +// implementation of basic_text_iprimitive overrides for the combination +// of template parameters used to implement a text_iprimitive + +#include <cstddef> // size_t, NULL +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/detail/workaround.hpp> // RogueWave + +#include <boost/archive/text_iarchive.hpp> + +namespace boost { +namespace archive { + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl<Archive>::load(char *s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + // Works on all tested platforms + is.read(s, size); + s[size] = '\0'; +} + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl<Archive>::load(std::string &s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != s.data()) + #endif + s.resize(size); + if(0 < size) + is.read(&(*s.begin()), size); +} + +#ifndef BOOST_NO_CWCHAR +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl<Archive>::load(wchar_t *ws) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + is.read((char *)ws, size * sizeof(wchar_t)/sizeof(char)); + ws[size] = L'\0'; +} +#endif // BOOST_NO_INTRINSIC_WCHAR_T + +#ifndef BOOST_NO_STD_WSTRING +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl<Archive>::load(std::wstring &ws) +{ + std::size_t size; + * this->This() >> size; + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != ws.data()) + #endif + ws.resize(size); + // skip separating space + is.get(); + is.read((char *)ws.data(), size * sizeof(wchar_t)/sizeof(char)); +} + +#endif // BOOST_NO_STD_WSTRING +#endif // BOOST_NO_CWCHAR + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl<Archive>::load_override(class_name_type & t, int){ + basic_text_iarchive<Archive>::load_override(t, 0); +} + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_iarchive_impl<Archive>::init(){ + basic_text_iarchive<Archive>::init(); +} + +template<class Archive> +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +text_iarchive_impl<Archive>::text_iarchive_impl( + std::istream & is, + unsigned int flags +) : + basic_text_iprimitive<std::istream>( + is, + 0 != (flags & no_codecvt) + ), + basic_text_iarchive<Archive>(flags) +{ + if(0 == (flags & no_header)) + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + this->init(); + #else + this->basic_text_iarchive<Archive>::init(); + #endif +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/text_oarchive_impl.ipp b/boost/boost/archive/impl/text_oarchive_impl.ipp new file mode 100644 index 0000000..2df0b46 --- /dev/null +++ b/boost/boost/archive/impl/text_oarchive_impl.ipp
@@ -0,0 +1,124 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_oarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <string> +#include <boost/config.hpp> +#include <locale> +#include <cstddef> // size_t + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#ifndef BOOST_NO_CWCHAR +#include <cwchar> +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::wcslen; } +#endif +#endif + +#include <boost/archive/add_facet.hpp> +#include <boost/archive/text_oarchive.hpp> + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of basic_text_oprimitive overrides for the combination +// of template parameters used to create a text_oprimitive + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl<Archive>::save(const char * s) +{ + const std::size_t len = std::ostream::traits_type::length(s); + *this->This() << len; + this->This()->newtoken(); + os << s; +} + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl<Archive>::save(const std::string &s) +{ + const std::size_t size = s.size(); + *this->This() << size; + this->This()->newtoken(); + os << s; +} + +#ifndef BOOST_NO_CWCHAR +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl<Archive>::save(const wchar_t * ws) +{ + const std::size_t l = std::wcslen(ws); + * this->This() << l; + this->This()->newtoken(); + os.write((const char *)ws, l * sizeof(wchar_t)/sizeof(char)); +} +#endif + +#ifndef BOOST_NO_STD_WSTRING +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl<Archive>::save(const std::wstring &ws) +{ + const std::size_t l = ws.size(); + * this->This() << l; + this->This()->newtoken(); + os.write((const char *)(ws.data()), l * sizeof(wchar_t)/sizeof(char)); +} +#endif +#endif // BOOST_NO_CWCHAR + +template<class Archive> +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +text_oarchive_impl<Archive>::text_oarchive_impl( + std::ostream & os, + unsigned int flags +) : + basic_text_oprimitive<std::ostream>( + os, + 0 != (flags & no_codecvt) + ), + basic_text_oarchive<Archive>(flags) +{ + if(0 == (flags & no_header)) + #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205)) + this->init(); + #else + this->basic_text_oarchive<Archive>::init(); + #endif +} + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +text_oarchive_impl<Archive>::save_binary(const void *address, std::size_t count){ + put('\n'); + this->end_preamble(); + #if ! defined(__MWERKS__) + this->basic_text_oprimitive<std::ostream>::save_binary( + #else + this->basic_text_oprimitive::save_binary( + #endif + address, + count + ); + this->delimiter = this->eol; +} + +} // namespace archive +} // namespace boost +
diff --git a/boost/boost/archive/impl/text_wiarchive_impl.ipp b/boost/boost/archive/impl/text_wiarchive_impl.ipp new file mode 100644 index 0000000..6938c22 --- /dev/null +++ b/boost/boost/archive/impl/text_wiarchive_impl.ipp
@@ -0,0 +1,118 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_text_wiarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstddef> // size_t, NULL + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/detail/workaround.hpp> // fixup for RogueWave + +#ifndef BOOST_NO_STD_WSTREAMBUF +#include <boost/archive/basic_text_iprimitive.hpp> + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of wiprimtives functions +// +template<class Archive> +BOOST_WARCHIVE_DECL(void) +text_wiarchive_impl<Archive>::load(char *s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + while(size-- > 0){ + *s++ = is.narrow(is.get(), '\0'); + } + *s = '\0'; +} + +template<class Archive> +BOOST_WARCHIVE_DECL(void) +text_wiarchive_impl<Archive>::load(std::string &s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != s.data()) + #endif + s.resize(0); + s.reserve(size); + while(size-- > 0){ + int x = is.narrow(is.get(), '\0'); + s += x; + } +} + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<class Archive> +BOOST_WARCHIVE_DECL(void) +text_wiarchive_impl<Archive>::load(wchar_t *s) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + // Works on all tested platforms + is.read(s, size); + s[size] = L'\0'; +} +#endif + +#ifndef BOOST_NO_STD_WSTRING +template<class Archive> +BOOST_WARCHIVE_DECL(void) +text_wiarchive_impl<Archive>::load(std::wstring &ws) +{ + std::size_t size; + * this->This() >> size; + // skip separating space + is.get(); + // borland complains about resize + // borland de-allocator fixup + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != ws.data()) + #endif + ws.resize(size); + // note breaking a rule here - is this a problem on some platform + is.read(const_cast<wchar_t *>(ws.data()), size); +} +#endif + +template<class Archive> +BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) +text_wiarchive_impl<Archive>::text_wiarchive_impl( + std::wistream & is, + unsigned int flags +) : + basic_text_iprimitive<std::wistream>( + is, + 0 != (flags & no_codecvt) + ), + basic_text_iarchive<Archive>(flags) +{ + if(0 == (flags & no_header)) + basic_text_iarchive<Archive>::init(); +} + +} // archive +} // boost + +#endif // BOOST_NO_STD_WSTREAMBUF
diff --git a/boost/boost/archive/impl/text_woarchive_impl.ipp b/boost/boost/archive/impl/text_woarchive_impl.ipp new file mode 100644 index 0000000..6683f52 --- /dev/null +++ b/boost/boost/archive/impl/text_woarchive_impl.ipp
@@ -0,0 +1,85 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_woarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifndef BOOST_NO_STD_WSTREAMBUF + +#include <cstring> +#include <cstddef> // size_t +#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__) +namespace std{ + using ::strlen; + using ::size_t; +} // namespace std +#endif + +#include <ostream> + +#include <boost/archive/text_woarchive.hpp> + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// implementation of woarchive functions +// +template<class Archive> +BOOST_WARCHIVE_DECL(void) +text_woarchive_impl<Archive>::save(const char *s) +{ + // note: superfluous local variable fixes borland warning + const std::size_t size = std::strlen(s); + * this->This() << size; + this->This()->newtoken(); + while(*s != '\0') + os.put(os.widen(*s++)); +} + +template<class Archive> +BOOST_WARCHIVE_DECL(void) +text_woarchive_impl<Archive>::save(const std::string &s) +{ + const std::size_t size = s.size(); + * this->This() << size; + this->This()->newtoken(); + const char * cptr = s.data(); + for(std::size_t i = size; i-- > 0;) + os.put(os.widen(*cptr++)); +} + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<class Archive> +BOOST_WARCHIVE_DECL(void) +text_woarchive_impl<Archive>::save(const wchar_t *ws) +{ + const std::size_t size = std::wostream::traits_type::length(ws); + * this->This() << size; + this->This()->newtoken(); + os.write(ws, size); +} +#endif + +#ifndef BOOST_NO_STD_WSTRING +template<class Archive> +BOOST_WARCHIVE_DECL(void) +text_woarchive_impl<Archive>::save(const std::wstring &ws) +{ + const std::size_t size = ws.length(); + * this->This() << size; + this->This()->newtoken(); + os.write(ws.data(), size); +} +#endif + +} // namespace archive +} // namespace boost + +#endif +
diff --git a/boost/boost/archive/impl/xml_iarchive_impl.ipp b/boost/boost/archive/impl/xml_iarchive_impl.ipp new file mode 100644 index 0000000..89e0981 --- /dev/null +++ b/boost/boost/archive/impl/xml_iarchive_impl.ipp
@@ -0,0 +1,193 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_iarchive_impl.cpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <cstring> // memcpy +#include <cstddef> // NULL +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} // namespace std +#endif + +#ifndef BOOST_NO_CWCHAR +#include <cstdlib> // mbtowc +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::mbtowc; + } // namespace std +#endif +#endif // BOOST_NO_CWCHAR + +#include <boost/detail/workaround.hpp> // RogueWave and Dinkumware +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) +#include <boost/archive/dinkumware.hpp> +#endif + +#include <boost/core/no_exceptions_support.hpp> + +#include <boost/archive/xml_archive_exception.hpp> +#include <boost/archive/iterators/dataflow_exception.hpp> +#include <boost/archive/basic_xml_archive.hpp> +#include <boost/archive/xml_iarchive.hpp> + +#include "basic_xml_grammar.hpp" + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions specific to char archives + +// wide char stuff used by char archives + +#ifndef BOOST_NO_CWCHAR +#ifndef BOOST_NO_STD_WSTRING +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl<Archive>::load(std::wstring &ws){ + std::string s; + bool result = gimpl->parse_string(is, s); + if(! result) + boost::serialization::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != ws.data()) + #endif + ws.resize(0); + const char * start = s.data(); + const char * end = start + s.size(); + while(start < end){ + wchar_t wc; + int resultx = std::mbtowc(&wc, start, end - start); + if(0 < resultx){ + start += resultx; + ws += wc; + continue; + } + boost::serialization::throw_exception( + iterators::dataflow_exception( + iterators::dataflow_exception::invalid_conversion + ) + ); + } +} +#endif // BOOST_NO_STD_WSTRING + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl<Archive>::load(wchar_t * ws){ + std::string s; + bool result = gimpl->parse_string(is, s); + if(! result) + boost::serialization::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + + const char * start = s.data(); + const char * end = start + s.size(); + while(start < end){ + wchar_t wc; + int length = std::mbtowc(&wc, start, end - start); + if(0 < length){ + start += length; + *ws++ = wc; + continue; + } + boost::serialization::throw_exception( + iterators::dataflow_exception( + iterators::dataflow_exception::invalid_conversion + ) + ); + } + *ws = L'\0'; +} +#endif // BOOST_NO_INTRINSIC_WCHAR_T + +#endif // BOOST_NO_CWCHAR + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl<Archive>::load(std::string &s){ + bool result = gimpl->parse_string(is, s); + if(! result) + boost::serialization::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); +} + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl<Archive>::load(char * s){ + std::string tstring; + bool result = gimpl->parse_string(is, tstring); + if(! result) + boost::serialization::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + std::memcpy(s, tstring.data(), tstring.size()); + s[tstring.size()] = 0; +} + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl<Archive>::load_override(class_name_type & t, int){ + const std::string & s = gimpl->rv.class_name; + if(s.size() > BOOST_SERIALIZATION_MAX_KEY_SIZE - 1) + boost::serialization::throw_exception( + archive_exception(archive_exception::invalid_class_name) + ); + char * tptr = t; + std::memcpy(tptr, s.data(), s.size()); + tptr[s.size()] = '\0'; +} + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_iarchive_impl<Archive>::init(){ + gimpl->init(is); + this->set_library_version( + library_version_type(gimpl->rv.version) + ); +} + +template<class Archive> +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_iarchive_impl<Archive>::xml_iarchive_impl( + std::istream &is_, + unsigned int flags +) : + basic_text_iprimitive<std::istream>( + is_, + 0 != (flags & no_codecvt) + ), + basic_xml_iarchive<Archive>(flags), + gimpl(new xml_grammar()) +{ + if(0 == (flags & no_header)) + init(); +} + +template<class Archive> +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_iarchive_impl<Archive>::~xml_iarchive_impl(){ + if(0 == (this->get_flags() & no_header)){ + BOOST_TRY{ + gimpl->windup(is); + } + BOOST_CATCH(...){} + BOOST_CATCH_END + } +} +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/xml_oarchive_impl.ipp b/boost/boost/archive/impl/xml_oarchive_impl.ipp new file mode 100644 index 0000000..ab1a217 --- /dev/null +++ b/boost/boost/archive/impl/xml_oarchive_impl.ipp
@@ -0,0 +1,117 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_oarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <ostream> +#include <iomanip> +#include <algorithm> // std::copy +#include <string> + +#include <cstring> // strlen +#include <boost/config.hpp> // msvc 6.0 needs this to suppress warnings +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::strlen; +} // namespace std +#endif + +#include <boost/archive/iterators/xml_escape.hpp> +#include <boost/archive/iterators/ostream_iterator.hpp> + +#ifndef BOOST_NO_CWCHAR +#include <boost/archive/wcslen.hpp> +#include <boost/archive/iterators/mb_from_wchar.hpp> +#endif + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions specific to char archives + +// wide char stuff used by char archives +#ifndef BOOST_NO_CWCHAR +// copy chars to output escaping to xml and translating wide chars to mb chars +template<class InputIterator> +void save_iterator(std::ostream &os, InputIterator begin, InputIterator end){ + typedef boost::archive::iterators::mb_from_wchar< + boost::archive::iterators::xml_escape<InputIterator> + > translator; + std::copy( + translator(BOOST_MAKE_PFTO_WRAPPER(begin)), + translator(BOOST_MAKE_PFTO_WRAPPER(end)), + boost::archive::iterators::ostream_iterator<char>(os) + ); +} + +#ifndef BOOST_NO_STD_WSTRING +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_oarchive_impl<Archive>::save(const std::wstring & ws){ +// at least one library doesn't typedef value_type for strings +// so rather than using string directly make a pointer iterator out of it +// save_iterator(os, ws.data(), ws.data() + std::wcslen(ws.data())); + save_iterator(os, ws.data(), ws.data() + ws.size()); +} +#endif + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_oarchive_impl<Archive>::save(const wchar_t * ws){ + save_iterator(os, ws, ws + std::wcslen(ws)); +} +#endif + +#endif // BOOST_NO_CWCHAR + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_oarchive_impl<Archive>::save(const std::string & s){ +// at least one library doesn't typedef value_type for strings +// so rather than using string directly make a pointer iterator out of it + typedef boost::archive::iterators::xml_escape< + const char * + > xml_escape_translator; + std::copy( + xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s.data())), + xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s.data()+ s.size())), + boost::archive::iterators::ostream_iterator<char>(os) + ); +} + +template<class Archive> +BOOST_ARCHIVE_DECL(void) +xml_oarchive_impl<Archive>::save(const char * s){ + typedef boost::archive::iterators::xml_escape< + const char * + > xml_escape_translator; + std::copy( + xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s)), + xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s + std::strlen(s))), + boost::archive::iterators::ostream_iterator<char>(os) + ); +} + +template<class Archive> +BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_oarchive_impl<Archive>::xml_oarchive_impl( + std::ostream & os_, + unsigned int flags +) : + basic_text_oprimitive<std::ostream>( + os_, + 0 != (flags & no_codecvt) + ), + basic_xml_oarchive<Archive>(flags) +{ + if(0 == (flags & no_header)) + this->init(); +} + +} // namespace archive +} // namespace boost
diff --git a/boost/boost/archive/impl/xml_wiarchive_impl.ipp b/boost/boost/archive/impl/xml_wiarchive_impl.ipp new file mode 100644 index 0000000..257b575 --- /dev/null +++ b/boost/boost/archive/impl/xml_wiarchive_impl.ipp
@@ -0,0 +1,194 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_wiarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstring> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; +} //std +#endif + +#include <boost/config.hpp> // msvc 6.0 needs this to suppress warnings +#ifndef BOOST_NO_STD_WSTREAMBUF + +#include <boost/assert.hpp> +#include <algorithm> // std::copy + +#include <boost/detail/workaround.hpp> // Dinkumware and RogueWave +#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) +#include <boost/archive/dinkumware.hpp> +#endif + +#include <boost/io/ios_state.hpp> +#include <boost/core/no_exceptions_support.hpp> +#include <boost/serialization/pfto.hpp> +#include <boost/serialization/string.hpp> + +#include <boost/archive/basic_xml_archive.hpp> +#include <boost/archive/xml_wiarchive.hpp> + +#include <boost/archive/add_facet.hpp> + +#include <boost/archive/xml_archive_exception.hpp> +#include <boost/archive/iterators/mb_from_wchar.hpp> + +#include "basic_xml_grammar.hpp" + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions specific to wide char archives + +namespace { // anonymous + +void copy_to_ptr(char * s, const std::wstring & ws){ + std::copy( + iterators::mb_from_wchar<std::wstring::const_iterator>( + BOOST_MAKE_PFTO_WRAPPER(ws.begin()) + ), + iterators::mb_from_wchar<std::wstring::const_iterator>( + BOOST_MAKE_PFTO_WRAPPER(ws.end()) + ), + s + ); + s[ws.size()] = 0; +} + +} // anonymous + +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl<Archive>::load(std::string & s){ + std::wstring ws; + bool result = gimpl->parse_string(is, ws); + if(! result) + boost::serialization::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101)) + if(NULL != s.data()) + #endif + s.resize(0); + s.reserve(ws.size()); + std::copy( + iterators::mb_from_wchar<std::wstring::iterator>( + BOOST_MAKE_PFTO_WRAPPER(ws.begin()) + ), + iterators::mb_from_wchar<std::wstring::iterator>( + BOOST_MAKE_PFTO_WRAPPER(ws.end()) + ), + std::back_inserter(s) + ); +} + +#ifndef BOOST_NO_STD_WSTRING +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl<Archive>::load(std::wstring & ws){ + bool result = gimpl->parse_string(is, ws); + if(! result) + boost::serialization::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); +} +#endif + +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl<Archive>::load(char * s){ + std::wstring ws; + bool result = gimpl->parse_string(is, ws); + if(! result) + boost::serialization::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + copy_to_ptr(s, ws); +} + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl<Archive>::load(wchar_t * ws){ + std::wstring twstring; + bool result = gimpl->parse_string(is, twstring); + if(! result) + boost::serialization::throw_exception( + xml_archive_exception(xml_archive_exception::xml_archive_parsing_error) + ); + std::memcpy(ws, twstring.c_str(), twstring.size()); + ws[twstring.size()] = L'\0'; +} +#endif + +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl<Archive>::load_override(class_name_type & t, int){ + const std::wstring & ws = gimpl->rv.class_name; + if(ws.size() > BOOST_SERIALIZATION_MAX_KEY_SIZE - 1) + boost::serialization::throw_exception( + archive_exception(archive_exception::invalid_class_name) + ); + copy_to_ptr(t, ws); +} + +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_wiarchive_impl<Archive>::init(){ + gimpl->init(is); + this->set_library_version( + library_version_type(gimpl->rv.version) + ); +} + +template<class Archive> +BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_wiarchive_impl<Archive>::xml_wiarchive_impl( + std::wistream &is_, + unsigned int flags +) : + basic_text_iprimitive<std::wistream>( + is_, + true // don't change the codecvt - use the one below + ), + basic_xml_iarchive<Archive>(flags), + gimpl(new xml_wgrammar()) +{ + if(0 == (flags & no_codecvt)){ + // note usage of argument "1" so that the locale isn't + // automatically delete the facet + archive_locale.reset( + add_facet( + is_.getloc(), + new boost::archive::detail::utf8_codecvt_facet + ) + ); + //is.imbue(* archive_locale); + } + if(0 == (flags & no_header)) + init(); +} + +template<class Archive> +BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_wiarchive_impl<Archive>::~xml_wiarchive_impl(){ + if(0 == (this->get_flags() & no_header)){ + BOOST_TRY{ + gimpl->windup(is); + } + BOOST_CATCH(...){} + BOOST_CATCH_END + } +} + +} // namespace archive +} // namespace boost + +#endif // BOOST_NO_STD_WSTREAMBUF
diff --git a/boost/boost/archive/impl/xml_woarchive_impl.ipp b/boost/boost/archive/impl/xml_woarchive_impl.ipp new file mode 100644 index 0000000..1e5139b --- /dev/null +++ b/boost/boost/archive/impl/xml_woarchive_impl.ipp
@@ -0,0 +1,151 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_woarchive_impl.ipp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/config.hpp> +#ifndef BOOST_NO_STD_WSTREAMBUF + +#include <ostream> +#include <string> +#include <algorithm> // std::copy +#include <locale> + +#include <cstring> // strlen +#include <cstdlib> // mbtowc +#include <cwchar> // wcslen + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::strlen; + #if ! defined(BOOST_NO_INTRINSIC_WCHAR_T) + using ::mbtowc; + using ::wcslen; + #endif +} // namespace std +#endif + +#include <boost/archive/xml_woarchive.hpp> +#include <boost/serialization/throw_exception.hpp> + +#include <boost/archive/iterators/xml_escape.hpp> +#include <boost/archive/iterators/wchar_from_mb.hpp> +#include <boost/archive/iterators/ostream_iterator.hpp> +#include <boost/archive/iterators/dataflow_exception.hpp> + +#include <boost/archive/add_facet.hpp> + +namespace boost { +namespace archive { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implemenations of functions specific to wide char archives + +// copy chars to output escaping to xml and widening characters as we go +template<class InputIterator> +void save_iterator(std::wostream &os, InputIterator begin, InputIterator end){ + typedef iterators::wchar_from_mb< + iterators::xml_escape<InputIterator> + > xmbtows; + std::copy( + xmbtows(BOOST_MAKE_PFTO_WRAPPER(begin)), + xmbtows(BOOST_MAKE_PFTO_WRAPPER(end)), + boost::archive::iterators::ostream_iterator<wchar_t>(os) + ); +} + +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_woarchive_impl<Archive>::save(const std::string & s){ + // note: we don't use s.begin() and s.end() because dinkumware + // doesn't have string::value_type defined. So use a wrapper + // around these values to implement the definitions. + const char * begin = s.data(); + const char * end = begin + s.size(); + save_iterator(os, begin, end); +} + +#ifndef BOOST_NO_STD_WSTRING +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_woarchive_impl<Archive>::save(const std::wstring & ws){ +#if 0 + typedef iterators::xml_escape<std::wstring::const_iterator> xmbtows; + std::copy( + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.begin())), + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.end())), + boost::archive::iterators::ostream_iterator<wchar_t>(os) + ); +#endif + typedef iterators::xml_escape<const wchar_t *> xmbtows; + std::copy( + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.data())), + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.data() + ws.size())), + boost::archive::iterators::ostream_iterator<wchar_t>(os) + ); +} +#endif //BOOST_NO_STD_WSTRING + +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_woarchive_impl<Archive>::save(const char * s){ + save_iterator(os, s, s + std::strlen(s)); +} + +#ifndef BOOST_NO_INTRINSIC_WCHAR_T +template<class Archive> +BOOST_WARCHIVE_DECL(void) +xml_woarchive_impl<Archive>::save(const wchar_t * ws){ + os << ws; + typedef iterators::xml_escape<const wchar_t *> xmbtows; + std::copy( + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws)), + xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws + std::wcslen(ws))), + boost::archive::iterators::ostream_iterator<wchar_t>(os) + ); +} +#endif + +template<class Archive> +BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_woarchive_impl<Archive>::xml_woarchive_impl( + std::wostream & os_, + unsigned int flags +) : + basic_text_oprimitive<std::wostream>( + os_, + true // don't change the codecvt - use the one below + ), + basic_xml_oarchive<Archive>(flags) +{ + // Standard behavior is that imbue can be called + // a) before output is invoked or + // b) after flush has been called. This prevents one-to-many + // transforms (such as one to many transforms from getting + // mixed up. + if(0 == (flags & no_codecvt)){ + archive_locale.reset( + add_facet( + os_.getloc(), + new boost::archive::detail::utf8_codecvt_facet + ) + ); + //os.imbue(* archive_locale); + } + if(0 == (flags & no_header)) + this->init(); +} + +template<class Archive> +BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) +xml_woarchive_impl<Archive>::~xml_woarchive_impl(){ +} + +} // namespace archive +} // namespace boost + +#endif //BOOST_NO_STD_WSTREAMBUF
diff --git a/boost/boost/archive/iterators/base64_exception.hpp b/boost/boost/archive/iterators/base64_exception.hpp new file mode 100644 index 0000000..8f9208b --- /dev/null +++ b/boost/boost/archive/iterators/base64_exception.hpp
@@ -0,0 +1,68 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_BASE64_EXCEPTION_HPP +#define BOOST_ARCHIVE_ITERATORS_BASE64_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// base64_exception.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifndef BOOST_NO_EXCEPTIONS +#include <exception> + +#include <boost/assert.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by base64s +// +class base64_exception : public std::exception +{ +public: + typedef enum { + invalid_code, // attempt to encode a value > 6 bits + invalid_character, // decode a value not in base64 char set + other_exception + } exception_code; + exception_code code; + + base64_exception(exception_code c = other_exception) : code(c) + {} + + virtual const char *what( ) const throw( ) + { + const char *msg = "unknown exception code"; + switch(code){ + case invalid_code: + msg = "attempt to encode a value > 6 bits"; + break; + case invalid_character: + msg = "attempt to decode a value not in base64 char set"; + break; + default: + BOOST_ASSERT(false); + break; + } + return msg; + } +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif //BOOST_NO_EXCEPTIONS +#endif //BOOST_ARCHIVE_ITERATORS_ARCHIVE_EXCEPTION_HPP
diff --git a/boost/boost/archive/iterators/base64_from_binary.hpp b/boost/boost/archive/iterators/base64_from_binary.hpp new file mode 100644 index 0000000..836d93d --- /dev/null +++ b/boost/boost/archive/iterators/base64_from_binary.hpp
@@ -0,0 +1,111 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_BASE64_FROM_BINARY_HPP +#define BOOST_ARCHIVE_ITERATORS_BASE64_FROM_BINARY_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// base64_from_binary.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> + +#include <cstddef> // size_t +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/serialization/pfto.hpp> + +#include <boost/iterator/transform_iterator.hpp> +#include <boost/archive/iterators/dataflow_exception.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// convert binary integers to base64 characters + +namespace detail { + +template<class CharType> +struct from_6_bit { + typedef CharType result_type; + CharType operator()(CharType t) const{ + const char * lookup_table = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/"; + BOOST_ASSERT(t < 64); + return lookup_table[static_cast<size_t>(t)]; + } +}; + +} // namespace detail + +// note: what we would like to do is +// template<class Base, class CharType = typename Base::value_type> +// typedef transform_iterator< +// from_6_bit<CharType>, +// transform_width<Base, 6, sizeof(Base::value_type) * 8, CharType> +// > base64_from_binary; +// but C++ won't accept this. Rather than using a "type generator" and +// using a different syntax, make a derivation which should be equivalent. +// +// Another issue addressed here is that the transform_iterator doesn't have +// a templated constructor. This makes it incompatible with the dataflow +// ideal. This is also addressed here. + +//template<class Base, class CharType = typename Base::value_type> +template< + class Base, + class CharType = typename boost::iterator_value<Base>::type +> +class base64_from_binary : + public transform_iterator< + detail::from_6_bit<CharType>, + Base + > +{ + friend class boost::iterator_core_access; + typedef transform_iterator< + typename detail::from_6_bit<CharType>, + Base + > super_t; + +public: + // make composible buy using templated constructor + template<class T> + base64_from_binary(BOOST_PFTO_WRAPPER(T) start) : + super_t( + Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start))), + detail::from_6_bit<CharType>() + ) + {} + // intel 7.1 doesn't like default copy constructor + base64_from_binary(const base64_from_binary & rhs) : + super_t( + Base(rhs.base_reference()), + detail::from_6_bit<CharType>() + ) + {} +// base64_from_binary(){}; +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_BASE64_FROM_BINARY_HPP
diff --git a/boost/boost/archive/iterators/binary_from_base64.hpp b/boost/boost/archive/iterators/binary_from_base64.hpp new file mode 100644 index 0000000..9d2c87e --- /dev/null +++ b/boost/boost/archive/iterators/binary_from_base64.hpp
@@ -0,0 +1,119 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE64_HPP +#define BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE64_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// binary_from_base64.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> + +#include <boost/serialization/throw_exception.hpp> +#include <boost/serialization/pfto.hpp> +#include <boost/static_assert.hpp> + +#include <boost/iterator/transform_iterator.hpp> +#include <boost/archive/iterators/dataflow_exception.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// convert base64 characters to binary data + +namespace detail { + +template<class CharType> +struct to_6_bit { + typedef CharType result_type; + CharType operator()(CharType t) const{ + const signed char lookup_table[] = { + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1, 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, + 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1 + }; + // metrowerks trips this assertion - how come? + #if ! defined(__MWERKS__) + BOOST_STATIC_ASSERT(128 == sizeof(lookup_table)); + #endif + signed char value = -1; + if((unsigned)t <= 127) + value = lookup_table[(unsigned)t]; + if(-1 == value) + boost::serialization::throw_exception( + dataflow_exception(dataflow_exception::invalid_base64_character) + ); + return value; + } +}; + +} // namespace detail + +// note: what we would like to do is +// template<class Base, class CharType = typename Base::value_type> +// typedef transform_iterator< +// from_6_bit<CharType>, +// transform_width<Base, 6, sizeof(Base::value_type) * 8, CharType> +// > base64_from_binary; +// but C++ won't accept this. Rather than using a "type generator" and +// using a different syntax, make a derivation which should be equivalent. +// +// Another issue addressed here is that the transform_iterator doesn't have +// a templated constructor. This makes it incompatible with the dataflow +// ideal. This is also addressed here. + +template< + class Base, + class CharType = typename boost::iterator_value<Base>::type +> +class binary_from_base64 : public + transform_iterator< + detail::to_6_bit<CharType>, + Base + > +{ + friend class boost::iterator_core_access; + typedef transform_iterator< + detail::to_6_bit<CharType>, + Base + > super_t; +public: + // make composible buy using templated constructor + template<class T> + binary_from_base64(BOOST_PFTO_WRAPPER(T) start) : + super_t( + Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start))), + detail::to_6_bit<CharType>() + ) + {} + // intel 7.1 doesn't like default copy constructor + binary_from_base64(const binary_from_base64 & rhs) : + super_t( + Base(rhs.base_reference()), + detail::to_6_bit<CharType>() + ) + {} +// binary_from_base64(){}; +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE64_HPP
diff --git a/boost/boost/archive/iterators/dataflow.hpp b/boost/boost/archive/iterators/dataflow.hpp new file mode 100644 index 0000000..6f8001d --- /dev/null +++ b/boost/boost/archive/iterators/dataflow.hpp
@@ -0,0 +1,103 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_DATAFLOW_HPP +#define BOOST_ARCHIVE_ITERATORS_DATAFLOW_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// dataflow.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> + +#include <boost/mpl/eval_if.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/mpl/apply.hpp> +#include <boost/mpl/plus.hpp> +#include <boost/mpl/int.hpp> + +#include <boost/type_traits/is_convertible.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/type_traits/is_pointer.hpp> +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/iterator/iterator_traits.hpp> +#include <boost/static_assert.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +// poor man's tri-state +struct tri_state { + enum state_enum { + is_false = false, + is_true = true, + is_indeterminant + } m_state; + // convert to bool + operator bool (){ + BOOST_ASSERT(is_indeterminant != m_state); + return is_true == m_state ? true : false; + } + // assign from bool + tri_state & operator=(bool rhs) { + m_state = rhs ? is_true : is_false; + return *this; + } + tri_state(bool rhs) : + m_state(rhs ? is_true : is_false) + {} + tri_state(state_enum state) : + m_state(state) + {} + bool operator==(const tri_state & rhs) const { + return m_state == rhs.m_state; + } + bool operator!=(const tri_state & rhs) const { + return m_state != rhs.m_state; + } +}; + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// implement functions common to dataflow iterators +template<class Derived> +class dataflow { + bool m_eoi; +protected: + // test for iterator equality + tri_state equal(const Derived & rhs) const { + if(m_eoi && rhs.m_eoi) + return true; + if(m_eoi || rhs.m_eoi) + return false; + return tri_state(tri_state::is_indeterminant); + } + void eoi(bool tf){ + m_eoi = tf; + } + bool eoi() const { + return m_eoi; + } +public: + dataflow(bool tf) : + m_eoi(tf) + {} + dataflow() : // used for iterator end + m_eoi(true) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_DATAFLOW_HPP
diff --git a/boost/boost/archive/iterators/dataflow_exception.hpp b/boost/boost/archive/iterators/dataflow_exception.hpp new file mode 100644 index 0000000..e3e1860 --- /dev/null +++ b/boost/boost/archive/iterators/dataflow_exception.hpp
@@ -0,0 +1,80 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_DATAFLOW_EXCEPTION_HPP +#define BOOST_ARCHIVE_ITERATORS_DATAFLOW_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// dataflow_exception.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifndef BOOST_NO_EXCEPTIONS +#include <exception> +#endif //BOOST_NO_EXCEPTIONS + +#include <boost/assert.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by dataflows +// +class dataflow_exception : public std::exception +{ +public: + typedef enum { + invalid_6_bitcode, + invalid_base64_character, + invalid_xml_escape_sequence, + comparison_not_permitted, + invalid_conversion, + other_exception + } exception_code; + exception_code code; + + dataflow_exception(exception_code c = other_exception) : code(c) + {} + + virtual const char *what( ) const throw( ) + { + const char *msg = "unknown exception code"; + switch(code){ + case invalid_6_bitcode: + msg = "attempt to encode a value > 6 bits"; + break; + case invalid_base64_character: + msg = "attempt to decode a value not in base64 char set"; + break; + case invalid_xml_escape_sequence: + msg = "invalid xml escape_sequence"; + break; + case comparison_not_permitted: + msg = "cannot invoke iterator comparison now"; + break; + case invalid_conversion: + msg = "invalid multbyte/wide char conversion"; + break; + default: + BOOST_ASSERT(false); + break; + } + return msg; + } +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif //BOOST_ARCHIVE_ITERATORS_DATAFLOW_EXCEPTION_HPP
diff --git a/boost/boost/archive/iterators/escape.hpp b/boost/boost/archive/iterators/escape.hpp new file mode 100644 index 0000000..a1fee91 --- /dev/null +++ b/boost/boost/archive/iterators/escape.hpp
@@ -0,0 +1,114 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_ESCAPE_HPP +#define BOOST_ARCHIVE_ITERATORS_ESCAPE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// escape.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> +#include <cstddef> // NULL + +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/iterator/iterator_traits.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// insert escapes into text + +template<class Derived, class Base> +class escape : + public boost::iterator_adaptor< + Derived, + Base, + typename boost::iterator_value<Base>::type, + single_pass_traversal_tag, + typename boost::iterator_value<Base>::type + > +{ + typedef typename boost::iterator_value<Base>::type base_value_type; + typedef typename boost::iterator_reference<Base>::type reference_type; + friend class boost::iterator_core_access; + + typedef typename boost::iterator_adaptor< + Derived, + Base, + base_value_type, + single_pass_traversal_tag, + base_value_type + > super_t; + + typedef escape<Derived, Base> this_t; + + void dereference_impl() { + m_current_value = static_cast<Derived *>(this)->fill(m_bnext, m_bend); + m_full = true; + } + + //Access the value referred to + reference_type dereference() const { + if(!m_full) + const_cast<this_t *>(this)->dereference_impl(); + return m_current_value; + } + + bool equal(const this_t & rhs) const { + if(m_full){ + if(! rhs.m_full) + const_cast<this_t *>(& rhs)->dereference_impl(); + } + else{ + if(rhs.m_full) + const_cast<this_t *>(this)->dereference_impl(); + } + if(m_bnext != rhs.m_bnext) + return false; + if(this->base_reference() != rhs.base_reference()) + return false; + return true; + } + + void increment(){ + if(++m_bnext < m_bend){ + m_current_value = *m_bnext; + return; + } + ++(this->base_reference()); + m_bnext = NULL; + m_bend = NULL; + m_full = false; + } + + // buffer to handle pending characters + const base_value_type *m_bnext; + const base_value_type *m_bend; + bool m_full; + base_value_type m_current_value; +public: + escape(Base base) : + super_t(base), + m_bnext(NULL), + m_bend(NULL), + m_full(false) + { + } +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_ESCAPE_HPP
diff --git a/boost/boost/archive/iterators/head_iterator.hpp b/boost/boost/archive/iterators/head_iterator.hpp new file mode 100644 index 0000000..6ad7d6b --- /dev/null +++ b/boost/boost/archive/iterators/head_iterator.hpp
@@ -0,0 +1,80 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_HEAD_ITERATOR_HPP +#define BOOST_ARCHIVE_ITERATORS_HEAD_ITERATOR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// head_iterator.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/iterator/iterator_traits.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +template<class Predicate, class Base> +class head_iterator + : public boost::iterator_adaptor< + head_iterator<Predicate, Base>, + Base, + use_default, + single_pass_traversal_tag + > +{ +private: + friend class iterator_core_access; + typedef boost::iterator_adaptor< + head_iterator<Predicate, Base>, + Base, + use_default, + single_pass_traversal_tag + > super_t; + + typedef head_iterator<Predicate, Base> this_t; + typedef super_t::value_type value_type; + typedef super_t::reference reference_type; + + reference_type dereference_impl(){ + if(! m_end){ + while(! m_predicate(* this->base_reference())) + ++ this->base_reference(); + m_end = true; + } + return * this->base_reference(); + } + + reference_type dereference() const { + return const_cast<this_t *>(this)->dereference_impl(); + } + + void increment(){ + ++base_reference(); + } + Predicate m_predicate; + bool m_end; +public: + template<class T> + head_iterator(Predicate f, T start) : + super_t(Base(start)), + m_predicate(f), + m_end(false) + {} + +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_HEAD_ITERATOR_HPP
diff --git a/boost/boost/archive/iterators/insert_linebreaks.hpp b/boost/boost/archive/iterators/insert_linebreaks.hpp new file mode 100644 index 0000000..7fbc79f --- /dev/null +++ b/boost/boost/archive/iterators/insert_linebreaks.hpp
@@ -0,0 +1,101 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_INSERT_LINEBREAKS_HPP +#define BOOST_ARCHIVE_ITERATORS_INSERT_LINEBREAKS_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// insert_linebreaks.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ using ::memcpy; } +#endif + +#include <boost/serialization/pfto.hpp> + +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/iterator/iterator_traits.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// insert line break every N characters +template< + class Base, + int N, + class CharType = typename boost::iterator_value<Base>::type +> +class insert_linebreaks : + public iterator_adaptor< + insert_linebreaks<Base, N, CharType>, + Base, + CharType, + single_pass_traversal_tag, + CharType + > +{ +private: + friend class boost::iterator_core_access; + typedef iterator_adaptor< + insert_linebreaks<Base, N, CharType>, + Base, + CharType, + single_pass_traversal_tag, + CharType + > super_t; + + bool equal(const insert_linebreaks<Base, N, CharType> & rhs) const { + return +// m_count == rhs.m_count +// && base_reference() == rhs.base_reference() + this->base_reference() == rhs.base_reference() + ; + } + + void increment() { + if(m_count == N){ + m_count = 0; + return; + } + ++m_count; + ++(this->base_reference()); + } + CharType dereference() const { + if(m_count == N) + return '\n'; + return * (this->base_reference()); + } + unsigned int m_count; +public: + // make composible buy using templated constructor + template<class T> + insert_linebreaks(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))), + m_count(0) + {} + // intel 7.1 doesn't like default copy constructor + insert_linebreaks(const insert_linebreaks & rhs) : + super_t(rhs.base_reference()), + m_count(rhs.m_count) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_INSERT_LINEBREAKS_HPP
diff --git a/boost/boost/archive/iterators/istream_iterator.hpp b/boost/boost/archive/iterators/istream_iterator.hpp new file mode 100644 index 0000000..41aa0be --- /dev/null +++ b/boost/boost/archive/iterators/istream_iterator.hpp
@@ -0,0 +1,107 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_ISTREAM_ITERATOR_HPP +#define BOOST_ARCHIVE_ITERATORS_ISTREAM_ITERATOR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// istream_iterator.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// note: this is a custom version of the standard istream_iterator. +// This is necessary as the standard version doesn't work as expected +// for wchar_t based streams on systems for which wchar_t not a true +// type but rather a synonym for some integer type. + +#include <cstddef> // NULL +#include <istream> +#include <boost/iterator/iterator_facade.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +// given a type, make an input iterator based on a pointer to that type +template<class Elem = char> +class istream_iterator : + public boost::iterator_facade< + istream_iterator<Elem>, + Elem, + std::input_iterator_tag, + Elem + > +{ + friend class boost::iterator_core_access; + typedef istream_iterator this_t ; + typedef typename boost::iterator_facade< + istream_iterator<Elem>, + Elem, + std::input_iterator_tag, + Elem + > super_t; + typedef typename std::basic_istream<Elem> istream_type; + + 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()); + if(! m_istream->good()){ + const_cast<this_t *>(this)->m_istream = NULL; + } + } + } +*/ + //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; +public: + istream_iterator(istream_type & is) : + m_istream(& is) + { + //increment(); + } + + istream_iterator() : + m_istream(NULL) + {} + + istream_iterator(const istream_iterator<Elem> & rhs) : + m_istream(rhs.m_istream), + m_current_value(rhs.m_current_value) + {} + +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_ISTREAM_ITERATOR_HPP
diff --git a/boost/boost/archive/iterators/mb_from_wchar.hpp b/boost/boost/archive/iterators/mb_from_wchar.hpp new file mode 100644 index 0000000..04e7c7e --- /dev/null +++ b/boost/boost/archive/iterators/mb_from_wchar.hpp
@@ -0,0 +1,136 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_MB_FROM_WCHAR_HPP +#define BOOST_ARCHIVE_ITERATORS_MB_FROM_WCHAR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// mb_from_wchar.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> +#include <cstddef> // size_t +#include <cstdlib> // for wctomb() + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; + using ::wctomb; +} // namespace std +#endif + +#include <boost/serialization/pfto.hpp> +#include <boost/iterator/iterator_adaptor.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// class used by text archives to translate wide strings and to char +// strings of the currently selected locale +template<class Base> // the input iterator +class mb_from_wchar + : public boost::iterator_adaptor< + mb_from_wchar<Base>, + Base, + wchar_t, + single_pass_traversal_tag, + char + > +{ + friend class boost::iterator_core_access; + + typedef typename boost::iterator_adaptor< + mb_from_wchar<Base>, + Base, + wchar_t, + single_pass_traversal_tag, + char + > super_t; + + typedef mb_from_wchar<Base> this_t; + + char dereference_impl() { + if(! m_full){ + fill(); + m_full = true; + } + return m_buffer[m_bnext]; + } + char dereference() const { + return (const_cast<this_t *>(this))->dereference_impl(); + } + + // test for iterator equality + bool equal(const mb_from_wchar<Base> & rhs) const { + // once the value is filled, the base_reference has been incremented + // so don't permit comparison anymore. + return + 0 == m_bend + && 0 == m_bnext + && this->base_reference() == rhs.base_reference() + ; + } + + void fill(){ + wchar_t value = * this->base_reference(); + #if (defined(__MINGW32__) && ((__MINGW32_MAJOR_VERSION > 3) \ + || ((__MINGW32_MAJOR_VERSION == 3) && (__MINGW32_MINOR_VERSION >= 8)))) + m_bend = std::wcrtomb(m_buffer, value, 0); + #else + m_bend = std::wctomb(m_buffer, value); + #endif + BOOST_ASSERT(-1 != m_bend); + BOOST_ASSERT((std::size_t)m_bend <= sizeof(m_buffer)); + BOOST_ASSERT(m_bend > 0); + m_bnext = 0; + } + + void increment(){ + if(++m_bnext < m_bend) + return; + m_bend = + m_bnext = 0; + ++(this->base_reference()); + m_full = false; + } + + // buffer to handle pending characters + int m_bend; + int m_bnext; + char m_buffer[9]; + bool m_full; + +public: + // make composible buy using templated constructor + template<class T> + mb_from_wchar(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))), + m_bend(0), + m_bnext(0), + m_full(false) + {} + // intel 7.1 doesn't like default copy constructor + mb_from_wchar(const mb_from_wchar & rhs) : + super_t(rhs.base_reference()), + m_bend(rhs.m_bend), + m_bnext(rhs.m_bnext), + m_full(rhs.m_full) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_MB_FROM_WCHAR_HPP
diff --git a/boost/boost/archive/iterators/ostream_iterator.hpp b/boost/boost/archive/iterators/ostream_iterator.hpp new file mode 100644 index 0000000..49a9b99 --- /dev/null +++ b/boost/boost/archive/iterators/ostream_iterator.hpp
@@ -0,0 +1,83 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_OSTREAM_ITERATOR_HPP +#define BOOST_ARCHIVE_ITERATORS_OSTREAM_ITERATOR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// ostream_iterator.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// note: this is a custom version of the standard ostream_iterator. +// This is necessary as the standard version doesn't work as expected +// for wchar_t based streams on systems for which wchar_t not a true +// type but rather a synonym for some integer type. + +#include <ostream> +#include <boost/iterator/iterator_facade.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +// given a type, make an input iterator based on a pointer to that type +template<class Elem> +class ostream_iterator : + public boost::iterator_facade< + ostream_iterator<Elem>, + Elem, + std::output_iterator_tag, + ostream_iterator<Elem> & + > +{ + friend class boost::iterator_core_access; + typedef ostream_iterator this_t ; + typedef Elem char_type; + typedef std::basic_ostream<char_type> ostream_type; + + //emulate the behavior of std::ostream + ostream_iterator & dereference() const { + return const_cast<ostream_iterator &>(*this); + } + bool equal(const this_t & rhs) const { + return m_ostream == rhs.m_ostream; + } + void increment(){} +protected: + ostream_type *m_ostream; + void put_val(char_type e){ + if(NULL != m_ostream){ + m_ostream->put(e); + if(! m_ostream->good()) + m_ostream = NULL; + } + } +public: + this_t & operator=(char_type c){ + put_val(c); + return *this; + } + ostream_iterator(ostream_type & os) : + m_ostream (& os) + {} + ostream_iterator() : + m_ostream (NULL) + {} + ostream_iterator(const ostream_iterator & rhs) : + m_ostream (rhs.m_ostream) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_OSTREAM_ITERATOR_HPP
diff --git a/boost/boost/archive/iterators/remove_whitespace.hpp b/boost/boost/archive/iterators/remove_whitespace.hpp new file mode 100644 index 0000000..4383987 --- /dev/null +++ b/boost/boost/archive/iterators/remove_whitespace.hpp
@@ -0,0 +1,169 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_REMOVE_WHITESPACE_HPP +#define BOOST_ARCHIVE_ITERATORS_REMOVE_WHITESPACE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// remove_whitespace.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> + +#include <boost/serialization/pfto.hpp> + +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/iterator/filter_iterator.hpp> +#include <boost/iterator/iterator_traits.hpp> + +// here is the default standard implementation of the functor used +// by the filter iterator to remove spaces. Unfortunately usage +// of this implementation in combination with spirit trips a bug +// VC 6.5. The only way I can find to work around it is to +// implement a special non-standard version for this platform + +#ifndef BOOST_NO_CWCTYPE +#include <cwctype> // iswspace +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ using ::iswspace; } +#endif +#endif + +#include <cctype> // isspace +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ using ::isspace; } +#endif + +#if defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER) +// this is required for the RW STL on Linux and Tru64. +#undef isspace +#undef iswspace +#endif + +namespace { // anonymous + +template<class CharType> +struct remove_whitespace_predicate; + +template<> +struct remove_whitespace_predicate<char> +{ + bool operator()(unsigned char t){ + return ! std::isspace(t); + } +}; + +#ifndef BOOST_NO_CWCHAR +template<> +struct remove_whitespace_predicate<wchar_t> +{ + bool operator()(wchar_t t){ + return ! std::iswspace(t); + } +}; +#endif + +} // namespace anonymous + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// convert base64 file data (including whitespace and padding) to binary + +namespace boost { +namespace archive { +namespace iterators { + +// custom version of filter iterator which doesn't look ahead further than +// necessary + +template<class Predicate, class Base> +class filter_iterator + : public boost::iterator_adaptor< + filter_iterator<Predicate, Base>, + Base, + use_default, + single_pass_traversal_tag + > +{ + friend class boost::iterator_core_access; + typedef typename boost::iterator_adaptor< + filter_iterator<Predicate, Base>, + Base, + use_default, + single_pass_traversal_tag + > super_t; + typedef filter_iterator<Predicate, Base> this_t; + typedef typename super_t::reference reference_type; + + reference_type dereference_impl(){ + if(! m_full){ + while(! m_predicate(* this->base_reference())) + ++(this->base_reference()); + m_full = true; + } + return * this->base_reference(); + } + + reference_type dereference() const { + return const_cast<this_t *>(this)->dereference_impl(); + } + + Predicate m_predicate; + bool m_full; +public: + // note: this function is public only because comeau compiler complained + // I don't know if this is because the compiler is wrong or what + void increment(){ + m_full = false; + ++(this->base_reference()); + } + filter_iterator(Base start) : + super_t(start), + m_full(false) + {} + filter_iterator(){} +}; + +template<class Base> +class remove_whitespace : + public filter_iterator< + remove_whitespace_predicate< + typename boost::iterator_value<Base>::type + //typename Base::value_type + >, + Base + > +{ + friend class boost::iterator_core_access; + typedef filter_iterator< + remove_whitespace_predicate< + typename boost::iterator_value<Base>::type + //typename Base::value_type + >, + Base + > super_t; +public: +// remove_whitespace(){} // why is this needed? + // make composible buy using templated constructor + template<class T> + remove_whitespace(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))) + {} + // intel 7.1 doesn't like default copy constructor + remove_whitespace(const remove_whitespace & rhs) : + super_t(rhs.base_reference()) + {} +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_REMOVE_WHITESPACE_HPP
diff --git a/boost/boost/archive/iterators/transform_width.hpp b/boost/boost/archive/iterators/transform_width.hpp new file mode 100644 index 0000000..15dd8df --- /dev/null +++ b/boost/boost/archive/iterators/transform_width.hpp
@@ -0,0 +1,178 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP +#define BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// transform_width.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// iterator which takes elements of x bits and returns elements of y bits. +// used to change streams of 8 bit characters into streams of 6 bit characters. +// and vice-versa for implementing base64 encodeing/decoding. Be very careful +// when using and end iterator. end is only reliable detected when the input +// stream length is some common multiple of x and y. E.G. Base64 6 bit +// character and 8 bit bytes. Lowest common multiple is 24 => 4 6 bit characters +// or 3 8 bit characters + +#include <boost/serialization/pfto.hpp> + +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/iterator/iterator_traits.hpp> + +#include <algorithm> // std::min + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// class used by text archives to translate char strings to wchar_t +// strings of the currently selected locale +template< + class Base, + int BitsOut, + int BitsIn, + class CharType = typename boost::iterator_value<Base>::type // output character +> +class transform_width : + public boost::iterator_adaptor< + transform_width<Base, BitsOut, BitsIn, CharType>, + Base, + CharType, + single_pass_traversal_tag, + CharType + > +{ + friend class boost::iterator_core_access; + typedef typename boost::iterator_adaptor< + transform_width<Base, BitsOut, BitsIn, CharType>, + Base, + CharType, + single_pass_traversal_tag, + CharType + > super_t; + + typedef transform_width<Base, BitsOut, BitsIn, CharType> this_t; + typedef typename iterator_value<Base>::type base_value_type; + + void fill(); + + CharType dereference() const { + if(!m_buffer_out_full) + const_cast<this_t *>(this)->fill(); + return m_buffer_out; + } + + 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 const_cast<this_t *>(this)->equal_impl(rhs); + } + + void increment(){ + m_buffer_out_full = false; + } + + 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_buffer_out_full(false), + // To disable GCC warning, but not truly necessary + //(m_buffer_in will be initialized later before being + //used because m_remaining_bits == 0) + m_buffer_in(0), + 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_buffer_out_full(rhs.m_buffer_out_full), + m_buffer_out(rhs.m_buffer_out), + m_buffer_in(rhs.m_buffer_in), + m_remaining_bits(rhs.m_remaining_bits), + m_end_of_sequence(false) + {} +}; + +template< + class Base, + int BitsOut, + int BitsIn, + class CharType +> +void transform_width<Base, BitsOut, BitsIn, CharType>::fill() { + unsigned int missing_bits = BitsOut; + 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; + } + } + + // 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 + 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 + m_buffer_out <<= i; + m_buffer_out |= j; + + // and update counters + missing_bits -= i; + m_remaining_bits -= i; + }while(0 < missing_bits); + m_buffer_out_full = true; +} + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP
diff --git a/boost/boost/archive/iterators/unescape.hpp b/boost/boost/archive/iterators/unescape.hpp new file mode 100644 index 0000000..abf6240 --- /dev/null +++ b/boost/boost/archive/iterators/unescape.hpp
@@ -0,0 +1,89 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_UNESCAPE_HPP +#define BOOST_ARCHIVE_ITERATORS_UNESCAPE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// unescape.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> + +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/pointee.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// class used by text archives to translate char strings to wchar_t +// strings of the currently selected locale +template<class Derived, class Base> +class unescape + : public boost::iterator_adaptor< + unescape<Derived, Base>, + Base, + typename pointee<Base>::type, + single_pass_traversal_tag, + typename pointee<Base>::type + > +{ + friend class boost::iterator_core_access; + typedef typename boost::iterator_adaptor< + unescape<Derived, Base>, + Base, + typename pointee<Base>::type, + single_pass_traversal_tag, + typename pointee<Base>::type + > super_t; + + typedef unescape<Derived, Base> this_t; +public: + typedef typename this_t::value_type value_type; + typedef typename this_t::reference reference; +private: + value_type dereference_impl() { + if(! m_full){ + m_current_value = static_cast<Derived *>(this)->drain(); + m_full = true; + } + return m_current_value; + } + + reference dereference() const { + return const_cast<this_t *>(this)->dereference_impl(); + } + + value_type m_current_value; + bool m_full; + + void increment(){ + ++(this->base_reference()); + dereference_impl(); + m_full = false; + }; + +public: + + unescape(Base base) : + super_t(base), + m_full(false) + {} + +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_UNESCAPE_HPP
diff --git a/boost/boost/archive/iterators/wchar_from_mb.hpp b/boost/boost/archive/iterators/wchar_from_mb.hpp new file mode 100644 index 0000000..ab81f17 --- /dev/null +++ b/boost/boost/archive/iterators/wchar_from_mb.hpp
@@ -0,0 +1,129 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP +#define BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// wchar_from_mb.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> +#include <cctype> +#include <cstddef> // size_t +#include <cstdlib> // mblen + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::mblen; + using ::mbtowc; +} // namespace std +#endif + +#include <boost/serialization/throw_exception.hpp> +#include <boost/serialization/pfto.hpp> + +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/archive/iterators/dataflow_exception.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// class used by text archives to translate char strings to wchar_t +// strings of the currently selected locale +template<class Base> +class wchar_from_mb + : public boost::iterator_adaptor< + wchar_from_mb<Base>, + Base, + wchar_t, + single_pass_traversal_tag, + wchar_t + > +{ + friend class boost::iterator_core_access; + typedef typename boost::iterator_adaptor< + wchar_from_mb<Base>, + Base, + wchar_t, + single_pass_traversal_tag, + wchar_t + > super_t; + + typedef wchar_from_mb<Base> this_t; + + wchar_t drain(); + + wchar_t dereference_impl() { + if(! m_full){ + m_current_value = drain(); + m_full = true; + } + return m_current_value; + } + + wchar_t dereference() const { + return const_cast<this_t *>(this)->dereference_impl(); + } + + void increment(){ + dereference_impl(); + m_full = false; + ++(this->base_reference()); + }; + + wchar_t m_current_value; + bool m_full; + +public: + // make composible buy using templated constructor + template<class T> + wchar_from_mb(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))), + m_full(false) + {} + // intel 7.1 doesn't like default copy constructor + wchar_from_mb(const wchar_from_mb & rhs) : + super_t(rhs.base_reference()), + m_full(rhs.m_full) + {} +}; + +template<class Base> +wchar_t wchar_from_mb<Base>::drain(){ + char buffer[9]; + char * bptr = buffer; + char val; + for(std::size_t i = 0; i++ < (unsigned)MB_CUR_MAX;){ + val = * this->base_reference(); + *bptr++ = val; + int result = std::mblen(buffer, i); + if(-1 != result) + break; + ++(this->base_reference()); + } + wchar_t retval; + int result = std::mbtowc(& retval, buffer, MB_CUR_MAX); + if(0 >= result) + boost::serialization::throw_exception(iterators::dataflow_exception( + iterators::dataflow_exception::invalid_conversion + )); + return retval; +} + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
diff --git a/boost/boost/archive/iterators/xml_escape.hpp b/boost/boost/archive/iterators/xml_escape.hpp new file mode 100644 index 0000000..a5d2c51 --- /dev/null +++ b/boost/boost/archive/iterators/xml_escape.hpp
@@ -0,0 +1,122 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_XML_ESCAPE_HPP +#define BOOST_ARCHIVE_ITERATORS_XML_ESCAPE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_escape.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> +#include <boost/serialization/pfto.hpp> +#include <boost/archive/iterators/escape.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// insert escapes into xml text + +template<class Base> +class xml_escape + : public escape<xml_escape<Base>, Base> +{ + friend class boost::iterator_core_access; + + typedef escape<xml_escape<Base>, Base> super_t; + +public: + char fill(const char * & bstart, const char * & bend); + wchar_t fill(const wchar_t * & bstart, const wchar_t * & bend); + + template<class T> + xml_escape(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))) + {} + // intel 7.1 doesn't like default copy constructor + xml_escape(const xml_escape & rhs) : + super_t(rhs.base_reference()) + {} +}; + +template<class Base> +char xml_escape<Base>::fill( + const char * & bstart, + const char * & bend +){ + char current_value = * this->base_reference(); + switch(current_value){ + case '<': + bstart = "<"; + bend = bstart + 4; + break; + case '>': + bstart = ">"; + bend = bstart + 4; + break; + case '&': + bstart = "&"; + bend = bstart + 5; + break; + case '"': + bstart = """; + bend = bstart + 6; + break; + case '\'': + bstart = "'"; + bend = bstart + 6; + break; + default: + return current_value; + } + return *bstart; +} + +template<class Base> +wchar_t xml_escape<Base>::fill( + const wchar_t * & bstart, + const wchar_t * & bend +){ + wchar_t current_value = * this->base_reference(); + switch(current_value){ + case '<': + bstart = L"<"; + bend = bstart + 4; + break; + case '>': + bstart = L">"; + bend = bstart + 4; + break; + case '&': + bstart = L"&"; + bend = bstart + 5; + break; + case '"': + bstart = L"""; + bend = bstart + 6; + break; + case '\'': + bstart = L"'"; + bend = bstart + 6; + break; + default: + return current_value; + } + return *bstart; +} + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_XML_ESCAPE_HPP
diff --git a/boost/boost/archive/iterators/xml_unescape.hpp b/boost/boost/archive/iterators/xml_unescape.hpp new file mode 100644 index 0000000..69438ed --- /dev/null +++ b/boost/boost/archive/iterators/xml_unescape.hpp
@@ -0,0 +1,126 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP +#define BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_unescape.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/assert.hpp> + +#include <boost/serialization/throw_exception.hpp> +#include <boost/serialization/pfto.hpp> + +#include <boost/archive/iterators/unescape.hpp> +#include <boost/archive/iterators/dataflow_exception.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// replace &??? xml escape sequences with the corresponding characters +template<class Base> +class xml_unescape + : public unescape<xml_unescape<Base>, Base> +{ + friend class boost::iterator_core_access; + typedef xml_unescape<Base> this_t; + typedef unescape<this_t, Base> super_t; + typedef typename boost::iterator_reference<this_t> reference_type; + + reference_type dereference() const { + return unescape<xml_unescape<Base>, Base>::dereference(); + } +public: + // workaround msvc 7.1 ICU crash + #if defined(BOOST_MSVC) + typedef int value_type; + #else + typedef typename this_t::value_type value_type; + #endif + + void drain_residue(const char *literal); + value_type drain(); + + template<class T> + xml_unescape(BOOST_PFTO_WRAPPER(T) start) : + super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))) + {} + // intel 7.1 doesn't like default copy constructor + xml_unescape(const xml_unescape & rhs) : + super_t(rhs.base_reference()) + {} +}; + +template<class Base> +void xml_unescape<Base>::drain_residue(const char * literal){ + do{ + if(* literal != * ++(this->base_reference())) + boost::serialization::throw_exception( + dataflow_exception( + dataflow_exception::invalid_xml_escape_sequence + ) + ); + } + while('\0' != * ++literal); +} + +// note key constraint on this function is that can't "look ahead" any +// more than necessary into base iterator. Doing so would alter the base +// iterator refenence which would make subsequent iterator comparisons +// incorrect and thereby break the composiblity of iterators. +template<class Base> +typename xml_unescape<Base>::value_type +//int +xml_unescape<Base>::drain(){ + value_type retval = * this->base_reference(); + if('&' != retval){ + return retval; + } + retval = * ++(this->base_reference()); + switch(retval){ + case 'l': // < + drain_residue("t;"); + retval = '<'; + break; + case 'g': // > + drain_residue("t;"); + retval = '>'; + break; + case 'a': + retval = * ++(this->base_reference()); + switch(retval){ + case 'p': // ' + drain_residue("os;"); + retval = '\''; + break; + case 'm': // & + drain_residue("p;"); + retval = '&'; + break; + } + break; + case 'q': + drain_residue("uot;"); + retval = '"'; + break; + } + return retval; +} + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif // BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP
diff --git a/boost/boost/archive/iterators/xml_unescape_exception.hpp b/boost/boost/archive/iterators/xml_unescape_exception.hpp new file mode 100644 index 0000000..71a6437 --- /dev/null +++ b/boost/boost/archive/iterators/xml_unescape_exception.hpp
@@ -0,0 +1,49 @@ +#ifndef BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_EXCEPTION_HPP +#define BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_unescape_exception.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifndef BOOST_NO_EXCEPTIONS +#include <exception> + +#include <boost/assert.hpp> + +namespace boost { +namespace archive { +namespace iterators { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by xml_unescapes +// +class xml_unescape_exception : public std::exception +{ +public: + xml_unescape_exception() + {} + + virtual const char *what( ) const throw( ) + { + return "xml contained un-recognized escape code"; + } +}; + +} // namespace iterators +} // namespace archive +} // namespace boost + +#endif //BOOST_NO_EXCEPTIONS +#endif //BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_EXCEPTION_HPP
diff --git a/boost/boost/archive/polymorphic_binary_iarchive.hpp b/boost/boost/archive/polymorphic_binary_iarchive.hpp new file mode 100644 index 0000000..4a898a8 --- /dev/null +++ b/boost/boost/archive/polymorphic_binary_iarchive.hpp
@@ -0,0 +1,54 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_BINARY_IARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_BINARY_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_binary_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <boost/archive/binary_iarchive.hpp> +#include <boost/archive/detail/polymorphic_iarchive_route.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +class polymorphic_binary_iarchive : + public detail::polymorphic_iarchive_route<binary_iarchive> +{ +public: + polymorphic_binary_iarchive(std::istream & is, unsigned int flags = 0) : + detail::polymorphic_iarchive_route<binary_iarchive>(is, flags) + {} + ~polymorphic_binary_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_binary_iarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_BINARY_IARCHIVE_HPP +
diff --git a/boost/boost/archive/polymorphic_binary_oarchive.hpp b/boost/boost/archive/polymorphic_binary_oarchive.hpp new file mode 100644 index 0000000..931b243 --- /dev/null +++ b/boost/boost/archive/polymorphic_binary_oarchive.hpp
@@ -0,0 +1,43 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_BINARY_OARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_BINARY_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_binary_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <boost/archive/binary_oarchive.hpp> +#include <boost/archive/detail/polymorphic_oarchive_route.hpp> + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + binary_oarchive_impl< + binary_oarchive, + std::ostream::char_type, + std::ostream::traits_type + > + > polymorphic_binary_oarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_binary_oarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_BINARY_OARCHIVE_HPP +
diff --git a/boost/boost/archive/polymorphic_iarchive.hpp b/boost/boost/archive/polymorphic_iarchive.hpp new file mode 100644 index 0000000..50488a3 --- /dev/null +++ b/boost/boost/archive/polymorphic_iarchive.hpp
@@ -0,0 +1,172 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_IARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstddef> // std::size_t +#include <climits> // ULONG_MAX +#include <string> + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/cstdint.hpp> + +#include <boost/serialization/pfto.hpp> +#include <boost/archive/detail/iserializer.hpp> +#include <boost/archive/detail/interface_iarchive.hpp> +#include <boost/serialization/nvp.hpp> +#include <boost/archive/detail/register_archive.hpp> + +#include <boost/archive/detail/decl.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization +namespace archive { +namespace detail { + class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive; + class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive; +} + +class polymorphic_iarchive; + +class polymorphic_iarchive_impl : + public detail::interface_iarchive<polymorphic_iarchive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_iarchive<polymorphic_iarchive>; + friend class load_access; +#endif + // primitive types the only ones permitted by polymorphic archives + virtual void load(bool & t) = 0; + + virtual void load(char & t) = 0; + virtual void load(signed char & t) = 0; + virtual void load(unsigned char & t) = 0; + #ifndef BOOST_NO_CWCHAR + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + virtual void load(wchar_t & t) = 0; + #endif + #endif + virtual void load(short & t) = 0; + virtual void load(unsigned short & t) = 0; + virtual void load(int & t) = 0; + virtual void load(unsigned int & t) = 0; + virtual void load(long & t) = 0; + virtual void load(unsigned long & t) = 0; + + #if defined(BOOST_HAS_LONG_LONG) + virtual void load(boost::long_long_type & t) = 0; + virtual void load(boost::ulong_long_type & t) = 0; + #elif defined(BOOST_HAS_MS_INT64) + virtual void load(__int64 & t) = 0; + virtual void load(unsigned __int64 & t) = 0; + #endif + + virtual void load(float & t) = 0; + virtual void load(double & t) = 0; + + // string types are treated as primitives + virtual void load(std::string & t) = 0; + #ifndef BOOST_NO_STD_WSTRING + virtual void load(std::wstring & t) = 0; + #endif + + // used for xml and other tagged formats + virtual void load_start(const char * name) = 0; + virtual void load_end(const char * name) = 0; + virtual void register_basic_serializer(const detail::basic_iserializer & bis) = 0; + + // msvc and borland won't automatically pass these to the base class so + // make it explicit here + template<class T> + void load_override(T & t, BOOST_PFTO int) + { + archive::load(* this->This(), t); + } + // special treatment for name-value pairs. + template<class T> + void load_override( + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + const + #endif + boost::serialization::nvp< T > & t, + int + ){ + load_start(t.name()); + archive::load(* this->This(), t.value()); + load_end(t.name()); + } +protected: + virtual ~polymorphic_iarchive_impl(){}; +public: + // utility function implemented by all legal archives + virtual void set_library_version(library_version_type archive_library_version) = 0; + virtual library_version_type get_library_version() const = 0; + virtual unsigned int get_flags() const = 0; + virtual void delete_created_pointers() = 0; + virtual void reset_object_address( + const void * new_address, + const void * old_address + ) = 0; + + virtual void load_binary(void * t, std::size_t size) = 0; + + // these are used by the serialization library implementation. + virtual void load_object( + void *t, + const detail::basic_iserializer & bis + ) = 0; + virtual const detail::basic_pointer_iserializer * load_pointer( + void * & t, + const detail::basic_pointer_iserializer * bpis_ptr, + const detail::basic_pointer_iserializer * (*finder)( + const boost::serialization::extended_type_info & type + ) + ) = 0; +}; + +} // namespace archive +} // namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +namespace boost { +namespace archive { + +class polymorphic_iarchive : + public polymorphic_iarchive_impl +{ +public: + virtual ~polymorphic_iarchive(){}; +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::polymorphic_iarchive) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_IARCHIVE_HPP
diff --git a/boost/boost/archive/polymorphic_oarchive.hpp b/boost/boost/archive/polymorphic_oarchive.hpp new file mode 100644 index 0000000..1eb9e0b --- /dev/null +++ b/boost/boost/archive/polymorphic_oarchive.hpp
@@ -0,0 +1,157 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_OARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstddef> // size_t +#include <climits> // ULONG_MAX +#include <string> + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/cstdint.hpp> +#include <boost/serialization/pfto.hpp> +#include <boost/archive/detail/oserializer.hpp> +#include <boost/archive/detail/interface_oarchive.hpp> +#include <boost/serialization/nvp.hpp> +#include <boost/archive/detail/register_archive.hpp> + +#include <boost/archive/detail/decl.hpp> +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace serialization { + class extended_type_info; +} // namespace serialization +namespace archive { +namespace detail { + class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive; + class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer; +} + +class polymorphic_oarchive; + +class polymorphic_oarchive_impl : + public detail::interface_oarchive<polymorphic_oarchive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else + friend class detail::interface_oarchive<polymorphic_oarchive>; + friend class save_access; +#endif + // primitive types the only ones permitted by polymorphic archives + virtual void save(const bool t) = 0; + + virtual void save(const char t) = 0; + virtual void save(const signed char t) = 0; + virtual void save(const unsigned char t) = 0; + #ifndef BOOST_NO_CWCHAR + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + virtual void save(const wchar_t t) = 0; + #endif + #endif + virtual void save(const short t) = 0; + virtual void save(const unsigned short t) = 0; + virtual void save(const int t) = 0; + virtual void save(const unsigned int t) = 0; + virtual void save(const long t) = 0; + virtual void save(const unsigned long t) = 0; + + #if defined(BOOST_HAS_LONG_LONG) + virtual void save(const boost::long_long_type t) = 0; + virtual void save(const boost::ulong_long_type t) = 0; + #elif defined(BOOST_HAS_MS_INT64) + virtual void save(const __int64 t) = 0; + virtual void save(const unsigned __int64 t) = 0; + #endif + + virtual void save(const float t) = 0; + virtual void save(const double t) = 0; + + // string types are treated as primitives + virtual void save(const std::string & t) = 0; + #ifndef BOOST_NO_STD_WSTRING + virtual void save(const std::wstring & t) = 0; + #endif + + virtual void save_null_pointer() = 0; + // used for xml and other tagged formats + virtual void save_start(const char * name) = 0; + virtual void save_end(const char * name) = 0; + virtual void register_basic_serializer(const detail::basic_oserializer & bos) = 0; + + virtual void end_preamble() = 0; + + // msvc and borland won't automatically pass these to the base class so + // make it explicit here + template<class T> + void save_override(T & t, BOOST_PFTO int) + { + archive::save(* this->This(), t); + } + // special treatment for name-value pairs. + template<class T> + void save_override( + #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING + const + #endif + ::boost::serialization::nvp< T > & t, int + ){ + save_start(t.name()); + archive::save(* this->This(), t.const_value()); + save_end(t.name()); + } +protected: + virtual ~polymorphic_oarchive_impl(){}; +public: + // utility functions implemented by all legal archives + virtual unsigned int get_flags() const = 0; + virtual library_version_type get_library_version() const = 0; + virtual void save_binary(const void * t, std::size_t size) = 0; + + virtual void save_object( + const void *x, + const detail::basic_oserializer & bos + ) = 0; + virtual void save_pointer( + const void * t, + const detail::basic_pointer_oserializer * bpos_ptr + ) = 0; +}; + +// note: preserve naming symmetry +class polymorphic_oarchive : + public polymorphic_oarchive_impl +{ +public: + virtual ~polymorphic_oarchive(){}; +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::polymorphic_oarchive) + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_POLYMORPHIC_OARCHIVE_HPP
diff --git a/boost/boost/archive/polymorphic_text_iarchive.hpp b/boost/boost/archive/polymorphic_text_iarchive.hpp new file mode 100644 index 0000000..7bef292 --- /dev/null +++ b/boost/boost/archive/polymorphic_text_iarchive.hpp
@@ -0,0 +1,54 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_IARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <boost/archive/text_iarchive.hpp> +#include <boost/archive/detail/polymorphic_iarchive_route.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +class polymorphic_text_iarchive : + public detail::polymorphic_iarchive_route<text_iarchive> +{ +public: + polymorphic_text_iarchive(std::istream & is, unsigned int flags = 0) : + detail::polymorphic_iarchive_route<text_iarchive>(is, flags) + {} + ~polymorphic_text_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_text_iarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_IARCHIVE_HPP +
diff --git a/boost/boost/archive/polymorphic_text_oarchive.hpp b/boost/boost/archive/polymorphic_text_oarchive.hpp new file mode 100644 index 0000000..457aad9 --- /dev/null +++ b/boost/boost/archive/polymorphic_text_oarchive.hpp
@@ -0,0 +1,39 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_OARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <boost/archive/text_oarchive.hpp> +#include <boost/archive/detail/polymorphic_oarchive_route.hpp> + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + text_oarchive_impl<text_oarchive> +> polymorphic_text_oarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_text_oarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_OARCHIVE_HPP +
diff --git a/boost/boost/archive/polymorphic_text_wiarchive.hpp b/boost/boost/archive/polymorphic_text_wiarchive.hpp new file mode 100644 index 0000000..8466f05 --- /dev/null +++ b/boost/boost/archive/polymorphic_text_wiarchive.hpp
@@ -0,0 +1,59 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_WIARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <boost/archive/text_wiarchive.hpp> +#include <boost/archive/detail/polymorphic_iarchive_route.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +class polymorphic_text_wiarchive : + public detail::polymorphic_iarchive_route<text_wiarchive> +{ +public: + polymorphic_text_wiarchive(std::wistream & is, unsigned int flags = 0) : + detail::polymorphic_iarchive_route<text_wiarchive>(is, flags) + {} + ~polymorphic_text_wiarchive(){} +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_text_wiarchive +) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_WIARCHIVE_HPP +
diff --git a/boost/boost/archive/polymorphic_text_woarchive.hpp b/boost/boost/archive/polymorphic_text_woarchive.hpp new file mode 100644 index 0000000..295625d --- /dev/null +++ b/boost/boost/archive/polymorphic_text_woarchive.hpp
@@ -0,0 +1,44 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_WOARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_text_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <boost/archive/text_woarchive.hpp> +#include <boost/archive/detail/polymorphic_oarchive_route.hpp> + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + text_woarchive_impl<text_woarchive> +> polymorphic_text_woarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_text_woarchive +) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_WOARCHIVE_HPP +
diff --git a/boost/boost/archive/polymorphic_xml_iarchive.hpp b/boost/boost/archive/polymorphic_xml_iarchive.hpp new file mode 100644 index 0000000..4dc3f89 --- /dev/null +++ b/boost/boost/archive/polymorphic_xml_iarchive.hpp
@@ -0,0 +1,54 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_IARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_XML_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_xml_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <boost/archive/xml_iarchive.hpp> +#include <boost/archive/detail/polymorphic_iarchive_route.hpp> + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +class polymorphic_xml_iarchive : + public detail::polymorphic_iarchive_route<xml_iarchive> +{ +public: + polymorphic_xml_iarchive(std::istream & is, unsigned int flags = 0) : + detail::polymorphic_iarchive_route<xml_iarchive>(is, flags) + {} + ~polymorphic_xml_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_xml_iarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_IARCHIVE_HPP +
diff --git a/boost/boost/archive/polymorphic_xml_oarchive.hpp b/boost/boost/archive/polymorphic_xml_oarchive.hpp new file mode 100644 index 0000000..514f9e5 --- /dev/null +++ b/boost/boost/archive/polymorphic_xml_oarchive.hpp
@@ -0,0 +1,39 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_OARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_XML_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_xml_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#include <boost/archive/xml_oarchive.hpp> +#include <boost/archive/detail/polymorphic_oarchive_route.hpp> + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + xml_oarchive_impl<xml_oarchive> +> polymorphic_xml_oarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_xml_oarchive +) + +#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_OARCHIVE_HPP +
diff --git a/boost/boost/archive/polymorphic_xml_wiarchive.hpp b/boost/boost/archive/polymorphic_xml_wiarchive.hpp new file mode 100644 index 0000000..d4ab731 --- /dev/null +++ b/boost/boost/archive/polymorphic_xml_wiarchive.hpp
@@ -0,0 +1,50 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_WIARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_XML_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_xml_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <boost/archive/xml_wiarchive.hpp> +#include <boost/archive/detail/polymorphic_iarchive_route.hpp> + +namespace boost { +namespace archive { + +class polymorphic_xml_wiarchive : + public detail::polymorphic_iarchive_route<xml_wiarchive> +{ +public: + polymorphic_xml_wiarchive(std::wistream & is, unsigned int flags = 0) : + detail::polymorphic_iarchive_route<xml_wiarchive>(is, flags) + {} + ~polymorphic_xml_wiarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_xml_wiarchive +) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_WIARCHIVE_HPP +
diff --git a/boost/boost/archive/polymorphic_xml_woarchive.hpp b/boost/boost/archive/polymorphic_xml_woarchive.hpp new file mode 100644 index 0000000..dd8963f --- /dev/null +++ b/boost/boost/archive/polymorphic_xml_woarchive.hpp
@@ -0,0 +1,44 @@ +#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_WOARCHIVE_HPP +#define BOOST_ARCHIVE_POLYMORPHIC_XML_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// polymorphic_xml_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <boost/archive/xml_woarchive.hpp> +#include <boost/archive/detail/polymorphic_oarchive_route.hpp> + +namespace boost { +namespace archive { + +typedef detail::polymorphic_oarchive_route< + xml_woarchive_impl<xml_woarchive> +> polymorphic_xml_woarchive; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE( + boost::archive::polymorphic_xml_woarchive +) + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_WOARCHIVE_HPP +
diff --git a/boost/boost/archive/text_iarchive.hpp b/boost/boost/archive/text_iarchive.hpp new file mode 100644 index 0000000..1fd0f60 --- /dev/null +++ b/boost/boost/archive/text_iarchive.hpp
@@ -0,0 +1,142 @@ +#ifndef BOOST_ARCHIVE_TEXT_IARCHIVE_HPP +#define BOOST_ARCHIVE_TEXT_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <istream> + +#include <boost/config.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/basic_text_iprimitive.hpp> +#include <boost/archive/basic_text_iarchive.hpp> +#include <boost/archive/detail/register_archive.hpp> +#include <boost/serialization/item_version_type.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_iarchive; +} // namespace detail + +template<class Archive> +class text_iarchive_impl : + public basic_text_iprimitive<std::istream>, + public basic_text_iarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive<Archive>; + friend load_access; + #else + friend class detail::interface_iarchive<Archive>; + friend class load_access; + #endif +#endif + template<class T> + void load(T & t){ + basic_text_iprimitive<std::istream>::load(t); + } + void load(version_type & t){ + unsigned int v; + load(v); + t = version_type(v); + } + void load(boost::serialization::item_version_type & t){ + unsigned int v; + load(v); + t = boost::serialization::item_version_type(v); + } + BOOST_ARCHIVE_DECL(void) + load(char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_ARCHIVE_DECL(void) + load(wchar_t * t); + #endif + BOOST_ARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + // note: the following should not needed - but one compiler (vc 7.1) + // fails to compile one test (test_shared_ptr) without it !!! + // make this protected so it can be called from a derived archive + template<class T> + void load_override(T & t, BOOST_PFTO int){ + basic_text_iarchive<Archive>::load_override(t, 0); + } + BOOST_ARCHIVE_DECL(void) + load_override(class_name_type & t, int); + BOOST_ARCHIVE_DECL(void) + init(); + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + text_iarchive_impl(std::istream & is, unsigned int flags); + // don't import inline definitions! leave this as a reminder. + //BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + ~text_iarchive_impl(){}; +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +class text_iarchive : + public text_iarchive_impl<text_iarchive>{ +public: + text_iarchive(std::istream & is_, unsigned int flags = 0) : + // note: added _ to suppress useless gcc warning + text_iarchive_impl<text_iarchive>(is_, flags) + {} + ~text_iarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_iarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_ARCHIVE_TEXT_IARCHIVE_HPP
diff --git a/boost/boost/archive/text_oarchive.hpp b/boost/boost/archive/text_oarchive.hpp new file mode 100644 index 0000000..9fd63a9 --- /dev/null +++ b/boost/boost/archive/text_oarchive.hpp
@@ -0,0 +1,129 @@ +#ifndef BOOST_ARCHIVE_TEXT_OARCHIVE_HPP +#define BOOST_ARCHIVE_TEXT_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <ostream> +#include <cstddef> // std::size_t + +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/basic_text_oprimitive.hpp> +#include <boost/archive/basic_text_oarchive.hpp> +#include <boost/archive/detail/register_archive.hpp> +#include <boost/serialization/item_version_type.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_oarchive; +} // namespace detail + +template<class Archive> +class text_oarchive_impl : + /* protected ? */ public basic_text_oprimitive<std::ostream>, + public basic_text_oarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive<Archive>; + friend basic_text_oarchive<Archive>; + friend save_access; + #else + friend class detail::interface_oarchive<Archive>; + friend class basic_text_oarchive<Archive>; + friend class save_access; + #endif +#endif + template<class T> + void save(const T & t){ + this->newtoken(); + basic_text_oprimitive<std::ostream>::save(t); + } + void save(const version_type & t){ + save(static_cast<const unsigned int>(t)); + } + void save(const boost::serialization::item_version_type & t){ + save(static_cast<const unsigned int>(t)); + } + BOOST_ARCHIVE_DECL(void) + save(const char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_ARCHIVE_DECL(void) + save(const wchar_t * t); + #endif + BOOST_ARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + text_oarchive_impl(std::ostream & os, unsigned int flags); + // don't import inline definitions! leave this as a reminder. + //BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + ~text_oarchive_impl(){}; +public: + BOOST_ARCHIVE_DECL(void) + save_binary(const void *address, std::size_t count); +}; + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from text_oarchive_impl instead. This will +// preserve correct static polymorphism. +class text_oarchive : + public text_oarchive_impl<text_oarchive> +{ +public: + text_oarchive(std::ostream & os_, unsigned int flags = 0) : + // note: added _ to suppress useless gcc warning + text_oarchive_impl<text_oarchive>(os_, flags) + {} + ~text_oarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_oarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_TEXT_OARCHIVE_HPP
diff --git a/boost/boost/archive/text_wiarchive.hpp b/boost/boost/archive/text_wiarchive.hpp new file mode 100644 index 0000000..5105d35 --- /dev/null +++ b/boost/boost/archive/text_wiarchive.hpp
@@ -0,0 +1,139 @@ +#ifndef BOOST_ARCHIVE_TEXT_WIARCHIVE_HPP +#define BOOST_ARCHIVE_TEXT_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <istream> + +#include <boost/archive/detail/auto_link_warchive.hpp> +#include <boost/archive/basic_text_iprimitive.hpp> +#include <boost/archive/basic_text_iarchive.hpp> +#include <boost/archive/detail/register_archive.hpp> +#include <boost/serialization/item_version_type.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_iarchive; +} // namespace detail + +template<class Archive> +class text_wiarchive_impl : + public basic_text_iprimitive<std::wistream>, + public basic_text_iarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive<Archive>; + friend load_access; + #else + friend class detail::interface_iarchive<Archive>; + friend class load_access; + #endif +#endif + template<class T> + void load(T & t){ + basic_text_iprimitive<std::wistream>::load(t); + } + void load(version_type & t){ + unsigned int v; + load(v); + t = version_type(v); + } + void load(boost::serialization::item_version_type & t){ + unsigned int v; + load(v); + t = boost::serialization::item_version_type(v); + } + BOOST_WARCHIVE_DECL(void) + load(char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_WARCHIVE_DECL(void) + load(wchar_t * t); + #endif + BOOST_WARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_WARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + // note: the following should not needed - but one compiler (vc 7.1) + // fails to compile one test (test_shared_ptr) without it !!! + template<class T> + void load_override(T & t, BOOST_PFTO int){ + basic_text_iarchive<Archive>::load_override(t, 0); + } + BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) + text_wiarchive_impl(std::wistream & is, unsigned int flags); + ~text_wiarchive_impl(){}; +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +class text_wiarchive : + public text_wiarchive_impl<text_wiarchive>{ +public: + text_wiarchive(std::wistream & is, unsigned int flags = 0) : + text_wiarchive_impl<text_wiarchive>(is, flags) + {} + ~text_wiarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_wiarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_TEXT_WIARCHIVE_HPP
diff --git a/boost/boost/archive/text_woarchive.hpp b/boost/boost/archive/text_woarchive.hpp new file mode 100644 index 0000000..2f75204 --- /dev/null +++ b/boost/boost/archive/text_woarchive.hpp
@@ -0,0 +1,155 @@ +#ifndef BOOST_ARCHIVE_TEXT_WOARCHIVE_HPP +#define BOOST_ARCHIVE_TEXT_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// text_woarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> + +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <ostream> +#include <cstddef> // size_t + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/archive/detail/auto_link_warchive.hpp> +#include <boost/archive/basic_text_oprimitive.hpp> +#include <boost/archive/basic_text_oarchive.hpp> +#include <boost/archive/detail/register_archive.hpp> +#include <boost/serialization/item_version_type.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_oarchive; +} // namespace detail + +template<class Archive> +class text_woarchive_impl : + public basic_text_oprimitive<std::wostream>, + public basic_text_oarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive<Archive>; + friend basic_text_oarchive<Archive>; + friend save_access; + #else + friend class detail::interface_oarchive<Archive>; + friend class basic_text_oarchive<Archive>; + friend class save_access; + #endif +#endif + template<class T> + void save(const T & t){ + this->newtoken(); + basic_text_oprimitive<std::wostream>::save(t); + } + void save(const version_type & t){ + save(static_cast<const unsigned int>(t)); + } + void save(const boost::serialization::item_version_type & t){ + save(static_cast<const unsigned int>(t)); + } + BOOST_WARCHIVE_DECL(void) + save(const char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_WARCHIVE_DECL(void) + save(const wchar_t * t); + #endif + BOOST_WARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_WARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + text_woarchive_impl(std::wostream & os, unsigned int flags) : + basic_text_oprimitive<std::wostream>( + os, + 0 != (flags & no_codecvt) + ), + basic_text_oarchive<Archive>(flags) + { + if(0 == (flags & no_header)) + basic_text_oarchive<Archive>::init(); + } +public: + void save_binary(const void *address, std::size_t count){ + put(static_cast<wchar_t>('\n')); + this->end_preamble(); + #if ! defined(__MWERKS__) + this->basic_text_oprimitive<std::wostream>::save_binary( + #else + this->basic_text_oprimitive::save_binary( + #endif + address, + count + ); + put(static_cast<wchar_t>('\n')); + this->delimiter = this->none; + } + +}; + +// we use the following because we can't use +// typedef text_oarchive_impl<text_oarchive_impl<...> > text_oarchive; + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from text_oarchive_impl instead. This will +// preserve correct static polymorphism. +class text_woarchive : + public text_woarchive_impl<text_woarchive> +{ +public: + text_woarchive(std::wostream & os, unsigned int flags = 0) : + text_woarchive_impl<text_woarchive>(os, flags) + {} + ~text_woarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_woarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_TEXT_WOARCHIVE_HPP
diff --git a/boost/boost/archive/tmpdir.hpp b/boost/boost/archive/tmpdir.hpp new file mode 100644 index 0000000..400d23b --- /dev/null +++ b/boost/boost/archive/tmpdir.hpp
@@ -0,0 +1,50 @@ +#ifndef BOOST_ARCHIVE_TMPDIR_HPP +#define BOOST_ARCHIVE_TMPDIR_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// tmpdir.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstdlib> // getenv +#include <cstddef> // NULL +//#include <boost/assert.hpp> + +#include <boost/config.hpp> +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { + using ::getenv; +} +#endif + +namespace boost { +namespace archive { + +inline const char * tmpdir(){ + const char *dirname; + dirname = std::getenv("TMP"); + if(NULL == dirname) + dirname = std::getenv("TMPDIR"); + if(NULL == dirname) + dirname = std::getenv("TEMP"); + if(NULL == dirname){ + //BOOST_ASSERT(false); // no temp directory found + dirname = "."; + } + return dirname; +} + +} // archive +} // boost + +#endif // BOOST_ARCHIVE_TMPDIR_HPP
diff --git a/boost/boost/archive/wcslen.hpp b/boost/boost/archive/wcslen.hpp new file mode 100644 index 0000000..2a3d635 --- /dev/null +++ b/boost/boost/archive/wcslen.hpp
@@ -0,0 +1,56 @@ +#ifndef BOOST_ARCHIVE_WCSLEN_HPP +#define BOOST_ARCHIVE_WCSLEN_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// wcslen.hpp: + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <cstddef> // size_t +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#ifndef BOOST_NO_CWCHAR + +// a couple of libraries which include wchar_t don't include +// wcslen + +#if defined(BOOST_DINKUMWARE_STDLIB) && BOOST_DINKUMWARE_STDLIB < 306 \ +|| defined(__LIBCOMO__) + +namespace std { +inline std::size_t wcslen(const wchar_t * ws) +{ + const wchar_t * eows = ws; + while(* eows != 0) + ++eows; + return eows - ws; +} +} // namespace std + +#else + +#include <cwchar> +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ using ::wcslen; } +#endif + +#endif // wcslen + +#endif //BOOST_NO_CWCHAR + +#endif //BOOST_ARCHIVE_WCSLEN_HPP
diff --git a/boost/boost/archive/xml_archive_exception.hpp b/boost/boost/archive/xml_archive_exception.hpp new file mode 100644 index 0000000..622cafe --- /dev/null +++ b/boost/boost/archive/xml_archive_exception.hpp
@@ -0,0 +1,56 @@ +#ifndef BOOST_ARCHIVE_XML_ARCHIVE_EXCEPTION_HPP +#define BOOST_ARCHIVE_XML_ARCHIVE_EXCEPTION_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_archive_exception.hpp: + +// (C) Copyright 2007 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <exception> +#include <boost/assert.hpp> + +#include <boost/config.hpp> +#include <boost/preprocessor/empty.hpp> +#include <boost/archive/detail/decl.hpp> +#include <boost/archive/archive_exception.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +namespace boost { +namespace archive { + +////////////////////////////////////////////////////////////////////// +// exceptions thrown by xml archives +// +class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) xml_archive_exception : + public virtual boost::archive::archive_exception +{ +public: + typedef enum { + xml_archive_parsing_error, // see save_register + xml_archive_tag_mismatch, + xml_archive_tag_name_error + } exception_code; + xml_archive_exception( + exception_code c, + const char * e1 = NULL, + const char * e2 = NULL + ); +}; + +}// namespace archive +}// namespace boost + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif //BOOST_XML_ARCHIVE_ARCHIVE_EXCEPTION_HPP
diff --git a/boost/boost/archive/xml_iarchive.hpp b/boost/boost/archive/xml_iarchive.hpp new file mode 100644 index 0000000..ecaeeeb --- /dev/null +++ b/boost/boost/archive/xml_iarchive.hpp
@@ -0,0 +1,150 @@ +#ifndef BOOST_ARCHIVE_XML_IARCHIVE_HPP +#define BOOST_ARCHIVE_XML_IARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_iarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <istream> + +#include <boost/scoped_ptr.hpp> +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/basic_text_iprimitive.hpp> +#include <boost/archive/basic_xml_iarchive.hpp> +#include <boost/archive/detail/register_archive.hpp> +#include <boost/serialization/item_version_type.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_iarchive; +} // namespace detail + +template<class CharType> +class basic_xml_grammar; +typedef basic_xml_grammar<char> xml_grammar; + +template<class Archive> +class xml_iarchive_impl : + public basic_text_iprimitive<std::istream>, + public basic_xml_iarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive<Archive>; + friend basic_xml_iarchive<Archive>; + friend load_access; + #else + friend class detail::interface_iarchive<Archive>; + friend class basic_xml_iarchive<Archive>; + friend class load_access; + #endif +#endif + // use boost:scoped_ptr to implement automatic deletion; + boost::scoped_ptr<xml_grammar> gimpl; + + std::istream & get_is(){ + return is; + } + template<class T> + void load(T & t){ + basic_text_iprimitive<std::istream>::load(t); + } + void + load(version_type & t){ + unsigned int v; + load(v); + t = version_type(v); + } + void + load(boost::serialization::item_version_type & t){ + unsigned int v; + load(v); + t = boost::serialization::item_version_type(v); + } + BOOST_ARCHIVE_DECL(void) + load(char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_ARCHIVE_DECL(void) + load(wchar_t * t); + #endif + BOOST_ARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + template<class T> + void load_override(T & t, BOOST_PFTO int){ + basic_xml_iarchive<Archive>::load_override(t, 0); + } + BOOST_ARCHIVE_DECL(void) + load_override(class_name_type & t, int); + BOOST_ARCHIVE_DECL(void) + init(); + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + xml_iarchive_impl(std::istream & is, unsigned int flags); + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + ~xml_iarchive_impl(); +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +class xml_iarchive : + public xml_iarchive_impl<xml_iarchive>{ +public: + xml_iarchive(std::istream & is, unsigned int flags = 0) : + xml_iarchive_impl<xml_iarchive>(is, flags) + {} + ~xml_iarchive(){}; +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_iarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_ARCHIVE_XML_IARCHIVE_HPP
diff --git a/boost/boost/archive/xml_oarchive.hpp b/boost/boost/archive/xml_oarchive.hpp new file mode 100644 index 0000000..2ac4ae1 --- /dev/null +++ b/boost/boost/archive/xml_oarchive.hpp
@@ -0,0 +1,143 @@ +#ifndef BOOST_ARCHIVE_XML_OARCHIVE_HPP +#define BOOST_ARCHIVE_XML_OARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_oarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <ostream> + +#include <cstddef> // size_t +#include <boost/config.hpp> +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <boost/archive/detail/auto_link_archive.hpp> +#include <boost/archive/basic_text_oprimitive.hpp> +#include <boost/archive/basic_xml_oarchive.hpp> +#include <boost/archive/detail/register_archive.hpp> +#include <boost/serialization/item_version_type.hpp> + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_oarchive; +} // namespace detail + +template<class Archive> +class xml_oarchive_impl : + public basic_text_oprimitive<std::ostream>, + public basic_xml_oarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive<Archive>; + friend basic_xml_oarchive<Archive>; + friend save_access; + #else + friend class detail::interface_oarchive<Archive>; + friend class basic_xml_oarchive<Archive>; + friend class save_access; + #endif +#endif + //void end_preamble(){ + // basic_xml_oarchive<Archive>::end_preamble(); + //} + template<class T> + void save(const T & t){ + basic_text_oprimitive<std::ostream>::save(t); + } + void + save(const version_type & t){ + save(static_cast<const unsigned int>(t)); + } + void + save(const boost::serialization::item_version_type & t){ + save(static_cast<const unsigned int>(t)); + } + BOOST_ARCHIVE_DECL(void) + save(const char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_ARCHIVE_DECL(void) + save(const wchar_t * t); + #endif + BOOST_ARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_ARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) + xml_oarchive_impl(std::ostream & os, unsigned int flags); + ~xml_oarchive_impl(){} +public: + void save_binary(const void *address, std::size_t count){ + this->end_preamble(); + #if ! defined(__MWERKS__) + this->basic_text_oprimitive<std::ostream>::save_binary( + #else + this->basic_text_oprimitive::save_binary( + #endif + address, + count + ); + this->indent_next = true; + } +}; + +// we use the following because we can't use +// typedef xml_oarchive_impl<xml_oarchive_impl<...> > xml_oarchive; + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from xml_oarchive_impl instead. This will +// preserve correct static polymorphism. +class xml_oarchive : + public xml_oarchive_impl<xml_oarchive> +{ +public: + xml_oarchive(std::ostream & os, unsigned int flags = 0) : + xml_oarchive_impl<xml_oarchive>(os, flags) + {} + ~xml_oarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_oarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_ARCHIVE_XML_OARCHIVE_HPP
diff --git a/boost/boost/archive/xml_wiarchive.hpp b/boost/boost/archive/xml_wiarchive.hpp new file mode 100644 index 0000000..a1baa1f --- /dev/null +++ b/boost/boost/archive/xml_wiarchive.hpp
@@ -0,0 +1,165 @@ +#ifndef BOOST_ARCHIVE_XML_WIARCHIVE_HPP +#define BOOST_ARCHIVE_XML_WIARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_wiarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <istream> + +#include <boost/smart_ptr/scoped_ptr.hpp> +#include <boost/archive/detail/auto_link_warchive.hpp> +#include <boost/archive/basic_text_iprimitive.hpp> +#include <boost/archive/basic_xml_iarchive.hpp> +#include <boost/archive/detail/register_archive.hpp> +#include <boost/serialization/item_version_type.hpp> + +#ifdef BOOST_NO_CXX11_HDR_CODECVT + #include <boost/archive/detail/utf8_codecvt_facet.hpp> +#else + #include <codecvt> + namespace boost { namespace archive { namespace detail { + typedef std::codecvt_utf8<wchar_t> utf8_codecvt_facet; + } } } +#endif + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_iarchive; +} // namespace detail + +template<class CharType> +class basic_xml_grammar; +typedef basic_xml_grammar<wchar_t> xml_wgrammar; + +template<class Archive> +class xml_wiarchive_impl : + public basic_text_iprimitive<std::wistream>, + public basic_xml_iarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_iarchive<Archive>; + friend basic_xml_iarchive<Archive>; + friend load_access; + #else + friend class detail::interface_iarchive<Archive>; + friend class basic_xml_iarchive<Archive>; + friend class load_access; + #endif +#endif + boost::scoped_ptr<xml_wgrammar> gimpl; + std::wistream & get_is(){ + return is; + } + template<class T> + void + load(T & t){ + basic_text_iprimitive<std::wistream>::load(t); + } + void + load(version_type & t){ + unsigned int v; + load(v); + t = version_type(v); + } + void + load(boost::serialization::item_version_type & t){ + unsigned int v; + load(v); + t = boost::serialization::item_version_type(v); + } + BOOST_WARCHIVE_DECL(void) + load(char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_WARCHIVE_DECL(void) + load(wchar_t * t); + #endif + BOOST_WARCHIVE_DECL(void) + load(std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_WARCHIVE_DECL(void) + load(std::wstring &ws); + #endif + template<class T> + void load_override(T & t, BOOST_PFTO int){ + basic_xml_iarchive<Archive>::load_override(t, 0); + } + BOOST_WARCHIVE_DECL(void) + load_override(class_name_type & t, int); + BOOST_WARCHIVE_DECL(void) + init(); + BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) + xml_wiarchive_impl(std::wistream & is, unsigned int flags) ; + BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~xml_wiarchive_impl(); +}; + +} // namespace archive +} // namespace boost + +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +class xml_wiarchive : + public xml_wiarchive_impl<xml_wiarchive>{ +public: + xml_wiarchive(std::wistream & is, unsigned int flags = 0) : + xml_wiarchive_impl<xml_wiarchive>(is, flags) + {} + ~xml_wiarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_wiarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_XML_WIARCHIVE_HPP
diff --git a/boost/boost/archive/xml_woarchive.hpp b/boost/boost/archive/xml_woarchive.hpp new file mode 100644 index 0000000..338bf74 --- /dev/null +++ b/boost/boost/archive/xml_woarchive.hpp
@@ -0,0 +1,161 @@ +#ifndef BOOST_ARCHIVE_XML_WOARCHIVE_HPP +#define BOOST_ARCHIVE_XML_WOARCHIVE_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// xml_woarchive.hpp + +// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +#include <boost/config.hpp> +#ifdef BOOST_NO_STD_WSTREAMBUF +#error "wide char i/o not supported on this platform" +#else + +#include <cstddef> // size_t +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::size_t; +} // namespace std +#endif + +#include <ostream> + +#include <boost/smart_ptr/scoped_ptr.hpp> +#include <boost/archive/detail/auto_link_warchive.hpp> +#include <boost/archive/basic_text_oprimitive.hpp> +#include <boost/archive/basic_xml_oarchive.hpp> +#include <boost/archive/detail/register_archive.hpp> +#include <boost/serialization/item_version_type.hpp> + +#ifdef BOOST_NO_CXX11_HDR_CODECVT + #include <boost/archive/detail/utf8_codecvt_facet.hpp> +#else + #include <codecvt> + namespace boost { namespace archive { namespace detail { + typedef std::codecvt_utf8<wchar_t> utf8_codecvt_facet; + } } } +#endif + +#include <boost/archive/detail/abi_prefix.hpp> // must be the last header + +#ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable : 4511 4512) +#endif + +namespace boost { +namespace archive { + +namespace detail { + template<class Archive> class interface_oarchive; +} // namespace detail + +template<class Archive> +class xml_woarchive_impl : + public basic_text_oprimitive<std::wostream>, + public basic_xml_oarchive<Archive> +{ +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +protected: + #if BOOST_WORKAROUND(BOOST_MSVC, < 1500) + // for some inexplicable reason insertion of "class" generates compile erro + // on msvc 7.1 + friend detail::interface_oarchive<Archive>; + friend basic_xml_oarchive<Archive>; + friend save_access; + #else + friend class detail::interface_oarchive<Archive>; + friend class basic_xml_oarchive<Archive>; + friend class save_access; + #endif +#endif + //void end_preamble(){ + // basic_xml_oarchive<Archive>::end_preamble(); + //} + template<class T> + void + save(const T & t){ + basic_text_oprimitive<std::wostream>::save(t); + } + void + save(const version_type & t){ + save(static_cast<const unsigned int>(t)); + } + void + save(const boost::serialization::item_version_type & t){ + save(static_cast<const unsigned int>(t)); + } + BOOST_WARCHIVE_DECL(void) + save(const char * t); + #ifndef BOOST_NO_INTRINSIC_WCHAR_T + BOOST_WARCHIVE_DECL(void) + save(const wchar_t * t); + #endif + BOOST_WARCHIVE_DECL(void) + save(const std::string &s); + #ifndef BOOST_NO_STD_WSTRING + BOOST_WARCHIVE_DECL(void) + save(const std::wstring &ws); + #endif + BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) + xml_woarchive_impl(std::wostream & os, unsigned int flags); + BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) + ~xml_woarchive_impl(); +public: + void + save_binary(const void *address, std::size_t count){ + this->end_preamble(); + #if ! defined(__MWERKS__) + this->basic_text_oprimitive<std::wostream>::save_binary( + #else + this->basic_text_oprimitive::save_binary( + #endif + address, + count + ); + this->indent_next = true; + } +}; + +// we use the following because we can't use +// typedef xml_woarchive_impl<xml_woarchive_impl<...> > xml_woarchive; + +// do not derive from this class. If you want to extend this functionality +// via inhertance, derived from xml_woarchive_impl instead. This will +// preserve correct static polymorphism. +class xml_woarchive : + public xml_woarchive_impl<xml_woarchive> +{ +public: + xml_woarchive(std::wostream & os, unsigned int flags = 0) : + xml_woarchive_impl<xml_woarchive>(os, flags) + {} + ~xml_woarchive(){} +}; + +} // namespace archive +} // namespace boost + +// required by export +BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_woarchive) + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include <boost/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas + +#endif // BOOST_NO_STD_WSTREAMBUF +#endif // BOOST_ARCHIVE_XML_OARCHIVE_HPP
diff --git a/boost/boost/array.hpp b/boost/boost/array.hpp new file mode 100644 index 0000000..fa06fa9 --- /dev/null +++ b/boost/boost/array.hpp
@@ -0,0 +1,446 @@ +/* The following code declares class array, + * an STL container (as wrapper) for arrays of constant size. + * + * See + * http://www.boost.org/libs/array/ + * for documentation. + * + * The original author site is at: http://www.josuttis.com/ + * + * (C) Copyright Nicolai M. Josuttis 2001. + * + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * 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 + * Eventually, we should remove "assign" which is now a synonym for "fill" (Marshall Clow) + * 10 Mar 2010 - added workaround for SUNCC and !STLPort [trac #3893] (Marshall Clow) + * 29 Jan 2004 - c_array() added, BOOST_NO_PRIVATE_IN_AGGREGATE removed (Nico Josuttis) + * 23 Aug 2002 - fix for Non-MSVC compilers combined with MSVC libraries. + * 05 Aug 2001 - minor update (Nico Josuttis) + * 20 Jan 2001 - STLport fix (Beman Dawes) + * 29 Sep 2000 - Initial Revision (Nico Josuttis) + * + * Jan 29, 2004 + */ +#ifndef BOOST_ARRAY_HPP +#define BOOST_ARRAY_HPP + +#include <boost/detail/workaround.hpp> + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(push) +# pragma warning(disable:4996) // 'std::equal': Function call with parameters that may be unsafe +# pragma warning(disable:4510) // boost::array<T,N>' : default constructor could not be generated +# pragma warning(disable:4610) // warning C4610: class 'boost::array<T,N>' can never be instantiated - user defined constructor required +#endif + +#include <cstddef> +#include <stdexcept> +#include <boost/assert.hpp> +#include <boost/swap.hpp> + +// 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 +#include <boost/config.hpp> + + +namespace boost { + + template<class T, std::size_t N> + class array { + public: + T elems[N]; // fixed-size array of elements of type T + + public: + // type definitions + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // iterator support + iterator begin() { return elems; } + const_iterator begin() const { return elems; } + const_iterator cbegin() const { return elems; } + + iterator end() { return elems+N; } + const_iterator end() const { return elems+N; } + const_iterator cend() const { return elems+N; } + + // reverse iterator support +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; +#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) + // workaround for broken reverse_iterator in VC7 + typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator, + reference, iterator, reference> > reverse_iterator; + typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator, + const_reference, iterator, reference> > const_reverse_iterator; +#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) + typedef std::reverse_iterator<iterator, std::random_access_iterator_tag, + value_type, reference, iterator, difference_type> reverse_iterator; + typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag, + value_type, const_reference, const_iterator, difference_type> const_reverse_iterator; +#else + // workaround for broken reverse_iterator implementations + typedef std::reverse_iterator<iterator,T> reverse_iterator; + typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator; +#endif + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator crbegin() const { + return const_reverse_iterator(end()); + } + + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + const_reverse_iterator crend() const { + return const_reverse_iterator(begin()); + } + + // operator[] + reference operator[](size_type i) + { + BOOST_ASSERT_MSG( i < N, "out of range" ); + return elems[i]; + } + + const_reference operator[](size_type i) const + { + BOOST_ASSERT_MSG( i < N, "out of range" ); + return elems[i]; + } + + // at() with range check + reference at(size_type i) { rangecheck(i); return elems[i]; } + const_reference at(size_type i) const { rangecheck(i); return elems[i]; } + + // front() and back() + reference front() + { + return elems[0]; + } + + const_reference front() const + { + return elems[0]; + } + + reference back() + { + return elems[N-1]; + } + + const_reference back() const + { + return elems[N-1]; + } + + // size is constant + static size_type size() { return N; } + static bool empty() { return false; } + static size_type max_size() { return N; } + enum { static_size = N }; + + // swap (note: linear complexity) + void swap (array<T,N>& y) { + for (size_type i = 0; i < N; ++i) + boost::swap(elems[i],y.elems[i]); + } + + // direct access to data (read-only) + const T* data() const { return elems; } + T* data() { return elems; } + + // use array as C array (direct read/write access to data) + T* c_array() { return elems; } + + // assignment with type conversion + template <typename T2> + array<T,N>& operator= (const array<T2,N>& rhs) { + std::copy(rhs.begin(),rhs.end(), begin()); + return *this; + } + + // assign one value to all elements + void assign (const T& value) { fill ( value ); } // A synonym for fill + void fill (const T& value) + { + std::fill_n(begin(),size(),value); + } + + // check range (may be private because it is static) + static void rangecheck (size_type i) { + if (i >= size()) { + std::out_of_range e("array<>: index out of range"); + boost::throw_exception(e); + } + } + + }; + +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + template< class T > + class array< T, 0 > { + + public: + // type definitions + typedef T value_type; + typedef T* iterator; + typedef const T* const_iterator; + typedef T& reference; + typedef const T& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + // iterator support + iterator begin() { return iterator( reinterpret_cast< T * >( this ) ); } + const_iterator begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); } + const_iterator cbegin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); } + + iterator end() { return begin(); } + const_iterator end() const { return begin(); } + const_iterator cend() const { return cbegin(); } + + // reverse iterator support +#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; +#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) + // workaround for broken reverse_iterator in VC7 + typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, iterator, + reference, iterator, reference> > reverse_iterator; + typedef std::reverse_iterator<std::_Ptrit<value_type, difference_type, const_iterator, + const_reference, iterator, reference> > const_reverse_iterator; +#elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) + typedef std::reverse_iterator<iterator, std::random_access_iterator_tag, + value_type, reference, iterator, difference_type> reverse_iterator; + typedef std::reverse_iterator<const_iterator, std::random_access_iterator_tag, + value_type, const_reference, const_iterator, difference_type> const_reverse_iterator; +#else + // workaround for broken reverse_iterator implementations + typedef std::reverse_iterator<iterator,T> reverse_iterator; + typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator; +#endif + + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + const_reverse_iterator crbegin() const { + return const_reverse_iterator(end()); + } + + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + const_reverse_iterator crend() const { + return const_reverse_iterator(begin()); + } + + // operator[] + reference operator[](size_type /*i*/) + { + return failed_rangecheck(); + } + + const_reference operator[](size_type /*i*/) const + { + return failed_rangecheck(); + } + + // at() with range check + reference at(size_type /*i*/) { return failed_rangecheck(); } + const_reference at(size_type /*i*/) const { return failed_rangecheck(); } + + // front() and back() + reference front() + { + return failed_rangecheck(); + } + + const_reference front() const + { + return failed_rangecheck(); + } + + reference back() + { + return failed_rangecheck(); + } + + const_reference back() const + { + return failed_rangecheck(); + } + + // size is constant + static size_type size() { return 0; } + static bool empty() { return true; } + static size_type max_size() { return 0; } + enum { static_size = 0 }; + + void swap (array<T,0>& /*y*/) { + } + + // direct access to data (read-only) + const T* data() const { return 0; } + T* data() { return 0; } + + // use array as C array (direct read/write access to data) + T* c_array() { return 0; } + + // assignment with type conversion + template <typename T2> + array<T,0>& operator= (const array<T2,0>& ) { + return *this; + } + + // assign one value to all elements + void assign (const T& value) { fill ( value ); } + void fill (const T& ) {} + + // check range (may be private because it is static) + static reference failed_rangecheck () { + std::out_of_range e("attempt to access element of an empty array"); + boost::throw_exception(e); +#if defined(BOOST_NO_EXCEPTIONS) || (!defined(BOOST_MSVC) && !defined(__PATHSCALE__)) + // + // We need to return something here to keep + // some compilers happy: however we will never + // actually get here.... + // + static T placeholder; + return placeholder; +#endif + } + }; +#endif + + // comparisons + template<class T, std::size_t N> + bool operator== (const array<T,N>& x, const array<T,N>& y) { + return std::equal(x.begin(), x.end(), y.begin()); + } + template<class T, std::size_t N> + bool operator< (const array<T,N>& x, const array<T,N>& y) { + return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end()); + } + template<class T, std::size_t N> + bool operator!= (const array<T,N>& x, const array<T,N>& y) { + return !(x==y); + } + template<class T, std::size_t N> + bool operator> (const array<T,N>& x, const array<T,N>& y) { + return y<x; + } + template<class T, std::size_t N> + bool operator<= (const array<T,N>& x, const array<T,N>& y) { + return !(y<x); + } + template<class T, std::size_t N> + bool operator>= (const array<T,N>& x, const array<T,N>& y) { + return !(x<y); + } + + // global swap() + template<class T, std::size_t N> + inline void swap (array<T,N>& x, array<T,N>& y) { + x.swap(y); + } + +#if defined(__SUNPRO_CC) +// Trac ticket #4757; the Sun Solaris compiler can't handle +// syntax like 'T(&get_c_array(boost::array<T,N>& arg))[N]' +// +// We can't just use this for all compilers, because the +// borland compilers can't handle this form. + namespace detail { + template <typename T, std::size_t N> struct c_array + { + typedef T type[N]; + }; + } + + // Specific for boost::array: simply returns its elems data member. + template <typename T, std::size_t N> + typename detail::c_array<T,N>::type& get_c_array(boost::array<T,N>& arg) + { + return arg.elems; + } + + // Specific for boost::array: simply returns its elems data member. + template <typename T, std::size_t N> + typename const detail::c_array<T,N>::type& get_c_array(const boost::array<T,N>& arg) + { + return arg.elems; + } +#else +// Specific for boost::array: simply returns its elems data member. + template <typename T, std::size_t N> + T(&get_c_array(boost::array<T,N>& arg))[N] + { + return arg.elems; + } + + // Const version. + template <typename T, std::size_t N> + const T(&get_c_array(const boost::array<T,N>& arg))[N] + { + return arg.elems; + } +#endif + +#if 0 + // Overload for std::array, assuming that std::array will have + // explicit conversion functions as discussed at the WG21 meeting + // in Summit, March 2009. + template <typename T, std::size_t N> + T(&get_c_array(std::array<T,N>& arg))[N] + { + return static_cast<T(&)[N]>(arg); + } + + // Const version. + template <typename T, std::size_t N> + const T(&get_c_array(const std::array<T,N>& arg))[N] + { + return static_cast<T(&)[N]>(arg); + } +#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 */ + + +#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) +# pragma warning(pop) +#endif + +#endif /*BOOST_ARRAY_HPP*/
diff --git a/boost/boost/asio.hpp b/boost/boost/asio.hpp new file mode 100644 index 0000000..67658a8 --- /dev/null +++ b/boost/boost/asio.hpp
@@ -0,0 +1,121 @@ +// +// asio.hpp +// ~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See www.boost.org/libs/asio for documentation. +// + +#ifndef BOOST_ASIO_HPP +#define BOOST_ASIO_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/async_result.hpp> +#include <boost/asio/basic_datagram_socket.hpp> +#include <boost/asio/basic_deadline_timer.hpp> +#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/basic_raw_socket.hpp> +#include <boost/asio/basic_seq_packet_socket.hpp> +#include <boost/asio/basic_serial_port.hpp> +#include <boost/asio/basic_signal_set.hpp> +#include <boost/asio/basic_socket_acceptor.hpp> +#include <boost/asio/basic_socket_iostream.hpp> +#include <boost/asio/basic_socket_streambuf.hpp> +#include <boost/asio/basic_stream_socket.hpp> +#include <boost/asio/basic_streambuf.hpp> +#include <boost/asio/basic_waitable_timer.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/asio/buffered_read_stream_fwd.hpp> +#include <boost/asio/buffered_read_stream.hpp> +#include <boost/asio/buffered_stream_fwd.hpp> +#include <boost/asio/buffered_stream.hpp> +#include <boost/asio/buffered_write_stream_fwd.hpp> +#include <boost/asio/buffered_write_stream.hpp> +#include <boost/asio/buffers_iterator.hpp> +#include <boost/asio/completion_condition.hpp> +#include <boost/asio/connect.hpp> +#include <boost/asio/coroutine.hpp> +#include <boost/asio/datagram_socket_service.hpp> +#include <boost/asio/deadline_timer_service.hpp> +#include <boost/asio/deadline_timer.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/generic/basic_endpoint.hpp> +#include <boost/asio/generic/datagram_protocol.hpp> +#include <boost/asio/generic/raw_protocol.hpp> +#include <boost/asio/generic/seq_packet_protocol.hpp> +#include <boost/asio/generic/stream_protocol.hpp> +#include <boost/asio/handler_alloc_hook.hpp> +#include <boost/asio/handler_continuation_hook.hpp> +#include <boost/asio/handler_invoke_hook.hpp> +#include <boost/asio/handler_type.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/ip/address.hpp> +#include <boost/asio/ip/address_v4.hpp> +#include <boost/asio/ip/address_v6.hpp> +#include <boost/asio/ip/basic_endpoint.hpp> +#include <boost/asio/ip/basic_resolver.hpp> +#include <boost/asio/ip/basic_resolver_entry.hpp> +#include <boost/asio/ip/basic_resolver_iterator.hpp> +#include <boost/asio/ip/basic_resolver_query.hpp> +#include <boost/asio/ip/host_name.hpp> +#include <boost/asio/ip/icmp.hpp> +#include <boost/asio/ip/multicast.hpp> +#include <boost/asio/ip/resolver_query_base.hpp> +#include <boost/asio/ip/resolver_service.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ip/udp.hpp> +#include <boost/asio/ip/unicast.hpp> +#include <boost/asio/ip/v6_only.hpp> +#include <boost/asio/is_read_buffered.hpp> +#include <boost/asio/is_write_buffered.hpp> +#include <boost/asio/local/basic_endpoint.hpp> +#include <boost/asio/local/connect_pair.hpp> +#include <boost/asio/local/datagram_protocol.hpp> +#include <boost/asio/local/stream_protocol.hpp> +#include <boost/asio/placeholders.hpp> +#include <boost/asio/posix/basic_descriptor.hpp> +#include <boost/asio/posix/basic_stream_descriptor.hpp> +#include <boost/asio/posix/descriptor_base.hpp> +#include <boost/asio/posix/stream_descriptor.hpp> +#include <boost/asio/posix/stream_descriptor_service.hpp> +#include <boost/asio/raw_socket_service.hpp> +#include <boost/asio/read.hpp> +#include <boost/asio/read_at.hpp> +#include <boost/asio/read_until.hpp> +#include <boost/asio/seq_packet_socket_service.hpp> +#include <boost/asio/serial_port.hpp> +#include <boost/asio/serial_port_base.hpp> +#include <boost/asio/serial_port_service.hpp> +#include <boost/asio/signal_set.hpp> +#include <boost/asio/signal_set_service.hpp> +#include <boost/asio/socket_acceptor_service.hpp> +#include <boost/asio/socket_base.hpp> +#include <boost/asio/strand.hpp> +#include <boost/asio/stream_socket_service.hpp> +#include <boost/asio/streambuf.hpp> +#include <boost/asio/time_traits.hpp> +#include <boost/asio/version.hpp> +#include <boost/asio/wait_traits.hpp> +#include <boost/asio/waitable_timer_service.hpp> +#include <boost/asio/windows/basic_handle.hpp> +#include <boost/asio/windows/basic_object_handle.hpp> +#include <boost/asio/windows/basic_random_access_handle.hpp> +#include <boost/asio/windows/basic_stream_handle.hpp> +#include <boost/asio/windows/object_handle.hpp> +#include <boost/asio/windows/object_handle_service.hpp> +#include <boost/asio/windows/overlapped_ptr.hpp> +#include <boost/asio/windows/random_access_handle.hpp> +#include <boost/asio/windows/random_access_handle_service.hpp> +#include <boost/asio/windows/stream_handle.hpp> +#include <boost/asio/windows/stream_handle_service.hpp> +#include <boost/asio/write.hpp> +#include <boost/asio/write_at.hpp> + +#endif // BOOST_ASIO_HPP
diff --git a/boost/boost/asio/async_result.hpp b/boost/boost/asio/async_result.hpp new file mode 100644 index 0000000..013fd9e --- /dev/null +++ b/boost/boost/asio/async_result.hpp
@@ -0,0 +1,96 @@ +// +// async_result.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_ASYNC_RESULT_HPP +#define BOOST_ASIO_ASYNC_RESULT_HPP + +#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/handler_type.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// An interface for customising the behaviour of an initiating function. +/** + * This template may be specialised for user-defined handler types. + */ +template <typename Handler> +class async_result +{ +public: + /// The return type of the initiating function. + typedef void type; + + /// Construct an async result from a given handler. + /** + * When using a specalised async_result, the constructor has an opportunity + * to initialise some state associated with the handler, which is then + * returned from the initiating function. + */ + explicit async_result(Handler&) + { + } + + /// Obtain the value to be returned from the initiating function. + type get() + { + } +}; + +namespace detail { + +// Helper template to deduce the true type of a handler, capture a local copy +// of the handler, and then create an async_result for the handler. +template <typename Handler, typename Signature> +struct async_result_init +{ + explicit async_result_init(BOOST_ASIO_MOVE_ARG(Handler) orig_handler) + : handler(BOOST_ASIO_MOVE_CAST(Handler)(orig_handler)), + result(handler) + { + } + + typename handler_type<Handler, Signature>::type handler; + async_result<typename handler_type<Handler, Signature>::type> result; +}; + +template <typename Handler, typename Signature> +struct async_result_type_helper +{ + typedef typename async_result< + typename handler_type<Handler, Signature>::type + >::type type; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#if defined(GENERATING_DOCUMENTATION) +# define BOOST_ASIO_INITFN_RESULT_TYPE(h, sig) \ + void_or_deduced +#elif defined(_MSC_VER) && (_MSC_VER < 1500) +# define BOOST_ASIO_INITFN_RESULT_TYPE(h, sig) \ + typename ::boost::asio::detail::async_result_type_helper<h, sig>::type +#else +# define BOOST_ASIO_INITFN_RESULT_TYPE(h, sig) \ + typename ::boost::asio::async_result< \ + typename ::boost::asio::handler_type<h, sig>::type>::type +#endif + +#endif // BOOST_ASIO_ASYNC_RESULT_HPP
diff --git a/boost/boost/asio/basic_datagram_socket.hpp b/boost/boost/asio/basic_datagram_socket.hpp new file mode 100644 index 0000000..f0ffe15 --- /dev/null +++ b/boost/boost/asio/basic_datagram_socket.hpp
@@ -0,0 +1,951 @@ +// +// basic_datagram_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP +#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/basic_socket.hpp> +#include <boost/asio/datagram_socket_service.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/error.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides datagram-oriented socket functionality. +/** + * The basic_datagram_socket class template provides asynchronous and blocking + * datagram-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename Protocol, + typename DatagramSocketService = datagram_socket_service<Protocol> > +class basic_datagram_socket + : public basic_socket<Protocol, DatagramSocketService> +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of a + /// socket. + typedef typename DatagramSocketService::native_handle_type native_type; + + /// The native representation of a socket. + typedef typename DatagramSocketService::native_handle_type native_handle_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_datagram_socket without opening it. + /** + * This constructor creates a datagram socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param io_service The io_service object that the datagram socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + */ + explicit basic_datagram_socket(boost::asio::io_service& io_service) + : basic_socket<Protocol, DatagramSocketService>(io_service) + { + } + + /// Construct and open a basic_datagram_socket. + /** + * This constructor creates and opens a datagram socket. + * + * @param io_service The io_service object that the datagram socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket<Protocol, DatagramSocketService>(io_service, protocol) + { + } + + /// Construct a basic_datagram_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a datagram socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param io_service The io_service object that the datagram socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param endpoint An endpoint on the local machine to which the datagram + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket<Protocol, DatagramSocketService>(io_service, endpoint) + { + } + + /// Construct a basic_datagram_socket on an existing native socket. + /** + * This constructor creates a datagram socket object to hold an existing + * native socket. + * + * @param io_service The io_service object that the datagram socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_datagram_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_handle_type& native_socket) + : basic_socket<Protocol, DatagramSocketService>( + io_service, protocol, native_socket) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_datagram_socket from another. + /** + * This constructor moves a datagram socket from one object to another. + * + * @param other The other basic_datagram_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_datagram_socket(io_service&) constructor. + */ + basic_datagram_socket(basic_datagram_socket&& other) + : basic_socket<Protocol, DatagramSocketService>( + BOOST_ASIO_MOVE_CAST(basic_datagram_socket)(other)) + { + } + + /// Move-assign a basic_datagram_socket from another. + /** + * This assignment operator moves a datagram socket from one object to + * another. + * + * @param other The other basic_datagram_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_datagram_socket(io_service&) constructor. + */ + basic_datagram_socket& operator=(basic_datagram_socket&& other) + { + basic_socket<Protocol, DatagramSocketService>::operator=( + BOOST_ASIO_MOVE_CAST(basic_datagram_socket)(other)); + return *this; + } + + /// Move-construct a basic_datagram_socket from a socket of another protocol + /// type. + /** + * This constructor moves a datagram socket from one object to another. + * + * @param other The other basic_datagram_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_datagram_socket(io_service&) constructor. + */ + template <typename Protocol1, typename DatagramSocketService1> + basic_datagram_socket( + basic_datagram_socket<Protocol1, DatagramSocketService1>&& other, + typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) + : basic_socket<Protocol, DatagramSocketService>( + BOOST_ASIO_MOVE_CAST2(basic_datagram_socket< + Protocol1, DatagramSocketService1>)(other)) + { + } + + /// Move-assign a basic_datagram_socket from a socket of another protocol + /// type. + /** + * This assignment operator moves a datagram socket from one object to + * another. + * + * @param other The other basic_datagram_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_datagram_socket(io_service&) constructor. + */ + template <typename Protocol1, typename DatagramSocketService1> + typename enable_if<is_convertible<Protocol1, Protocol>::value, + basic_datagram_socket>::type& operator=( + basic_datagram_socket<Protocol1, DatagramSocketService1>&& other) + { + basic_socket<Protocol, DatagramSocketService>::operator=( + BOOST_ASIO_MOVE_CAST2(basic_datagram_socket< + Protocol1, DatagramSocketService1>)(other)); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Send some data on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected datagram socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code socket.send(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected datagram socket. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the datagram socket. The function + * call will block until the data has been sent successfully or an error + * occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected datagram socket. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->get_service().send( + this->get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to asynchronously send data on the datagram socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected datagram + * socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send(this->get_implementation(), + buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to asynchronously send data on the datagram socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected datagram + * socket. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send(this->get_implementation(), + buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Send a datagram to the specified endpoint. + /** + * This function is used to send a datagram to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.send_to(boost::asio::buffer(data, size), destination); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send_to( + this->get_implementation(), buffers, destination, 0, ec); + boost::asio::detail::throw_error(ec, "send_to"); + return s; + } + + /// Send a datagram to the specified endpoint. + /** + * This function is used to send a datagram to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ConstBufferSequence> + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send_to( + this->get_implementation(), buffers, destination, flags, ec); + boost::asio::detail::throw_error(ec, "send_to"); + return s; + } + + /// Send a datagram to the specified endpoint. + /** + * This function is used to send a datagram to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + */ + template <typename ConstBufferSequence> + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->get_service().send_to(this->get_implementation(), + buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send a datagram to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_send_to( + * boost::asio::buffer(data, size), destination, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send_to( + this->get_implementation(), buffers, destination, 0, + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send a datagram to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send_to( + this->get_implementation(), buffers, destination, flags, + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the datagram socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected datagram + * socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.receive(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the datagram socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected datagram + * socket. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the datagram socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected datagram + * socket. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->get_service().receive( + this->get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the datagram + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * datagram socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the datagram + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * datagram socket. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Receive a datagram with the endpoint of the sender. + /** + * This function is used to receive a datagram. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * boost::asio::ip::udp::endpoint sender_endpoint; + * socket.receive_from( + * boost::asio::buffer(data, size), sender_endpoint); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive_from( + this->get_implementation(), buffers, sender_endpoint, 0, ec); + boost::asio::detail::throw_error(ec, "receive_from"); + return s; + } + + /// Receive a datagram with the endpoint of the sender. + /** + * This function is used to receive a datagram. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename MutableBufferSequence> + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive_from( + this->get_implementation(), buffers, sender_endpoint, flags, ec); + boost::asio::detail::throw_error(ec, "receive_from"); + return s; + } + + /// Receive a datagram with the endpoint of the sender. + /** + * This function is used to receive a datagram. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + */ + template <typename MutableBufferSequence> + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->get_service().receive_from(this->get_implementation(), + buffers, sender_endpoint, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive a datagram. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.async_receive_from( + * boost::asio::buffer(data, size), sender_endpoint, handler); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive_from( + this->get_implementation(), buffers, sender_endpoint, 0, + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive a datagram. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the datagram. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive_from( + this->get_implementation(), buffers, sender_endpoint, flags, + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
diff --git a/boost/boost/asio/basic_deadline_timer.hpp b/boost/boost/asio/basic_deadline_timer.hpp new file mode 100644 index 0000000..27a75f3 --- /dev/null +++ b/boost/boost/asio/basic_deadline_timer.hpp
@@ -0,0 +1,520 @@ +// +// basic_deadline_timer.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP +#define BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ + || defined(GENERATING_DOCUMENTATION) + +#include <cstddef> +#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/deadline_timer_service.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides waitable timer functionality. +/** + * The basic_deadline_timer class template provides the ability to perform a + * blocking or asynchronous wait for a timer to expire. + * + * A deadline timer is always in one of two states: "expired" or "not expired". + * If the wait() or async_wait() function is called on an expired timer, the + * wait operation will complete immediately. + * + * Most applications will use the boost::asio::deadline_timer typedef. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Examples + * Performing a blocking wait: + * @code + * // Construct a timer without setting an expiry time. + * boost::asio::deadline_timer timer(io_service); + * + * // Set an expiry time relative to now. + * timer.expires_from_now(boost::posix_time::seconds(5)); + * + * // Wait for the timer to expire. + * timer.wait(); + * @endcode + * + * @par + * Performing an asynchronous wait: + * @code + * void handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Timer expired. + * } + * } + * + * ... + * + * // Construct a timer with an absolute expiry time. + * boost::asio::deadline_timer timer(io_service, + * boost::posix_time::time_from_string("2005-12-07 23:59:59.000")); + * + * // Start an asynchronous wait. + * timer.async_wait(handler); + * @endcode + * + * @par Changing an active deadline_timer's expiry time + * + * Changing the expiry time of a timer while there are pending asynchronous + * waits causes those wait operations to be cancelled. To ensure that the action + * associated with the timer is performed only once, use something like this: + * used: + * + * @code + * void on_some_event() + * { + * if (my_timer.expires_from_now(seconds(5)) > 0) + * { + * // We managed to cancel the timer. Start new asynchronous wait. + * my_timer.async_wait(on_timeout); + * } + * else + * { + * // Too late, timer has already expired! + * } + * } + * + * void on_timeout(const boost::system::error_code& e) + * { + * if (e != boost::asio::error::operation_aborted) + * { + * // Timer was not cancelled, take necessary action. + * } + * } + * @endcode + * + * @li The boost::asio::basic_deadline_timer::expires_from_now() function + * cancels any pending asynchronous waits, and returns the number of + * asynchronous waits that were cancelled. If it returns 0 then you were too + * late and the wait handler has already been executed, or will soon be + * executed. If it returns 1 then the wait handler was successfully cancelled. + * + * @li If a wait handler is cancelled, the boost::system::error_code passed to + * it contains the value boost::asio::error::operation_aborted. + */ +template <typename Time, + typename TimeTraits = boost::asio::time_traits<Time>, + typename TimerService = deadline_timer_service<Time, TimeTraits> > +class basic_deadline_timer + : public basic_io_object<TimerService> +{ +public: + /// The time traits type. + typedef TimeTraits traits_type; + + /// The time type. + typedef typename traits_type::time_type time_type; + + /// The duration type. + typedef typename traits_type::duration_type duration_type; + + /// Constructor. + /** + * This constructor creates a timer without setting an expiry time. The + * expires_at() or expires_from_now() functions must be called to set an + * expiry time before the timer can be waited on. + * + * @param io_service The io_service object that the timer will use to dispatch + * handlers for any asynchronous operations performed on the timer. + */ + explicit basic_deadline_timer(boost::asio::io_service& io_service) + : basic_io_object<TimerService>(io_service) + { + } + + /// Constructor to set a particular expiry time as an absolute time. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param io_service The io_service object that the timer will use to dispatch + * handlers for any asynchronous operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, expressed + * as an absolute time. + */ + basic_deadline_timer(boost::asio::io_service& io_service, + const time_type& expiry_time) + : basic_io_object<TimerService>(io_service) + { + boost::system::error_code ec; + this->service.expires_at(this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_at"); + } + + /// Constructor to set a particular expiry time relative to now. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param io_service The io_service object that the timer will use to dispatch + * handlers for any asynchronous operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, relative to + * now. + */ + basic_deadline_timer(boost::asio::io_service& io_service, + const duration_type& expiry_time) + : basic_io_object<TimerService>(io_service) + { + boost::system::error_code ec; + this->service.expires_from_now(this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_from_now"); + } + + /// Cancel any asynchronous operations that are waiting on the timer. + /** + * This function forces the completion of any pending asynchronous wait + * operations against the timer. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @return The number of asynchronous operations that were cancelled. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note If the timer has already expired when cancel() is called, then the + * handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t cancel() + { + boost::system::error_code ec; + std::size_t s = this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec, "cancel"); + return s; + } + + /// Cancel any asynchronous operations that are waiting on the timer. + /** + * This function forces the completion of any pending asynchronous wait + * operations against the timer. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. + * + * @note If the timer has already expired when cancel() is called, then the + * handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Cancels one asynchronous operation that is waiting on the timer. + /** + * This function forces the completion of one pending asynchronous wait + * operation against the timer. Handlers are cancelled in FIFO order. The + * handler for the cancelled operation will be invoked with the + * boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @return The number of asynchronous operations that were cancelled. That is, + * either 0 or 1. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note If the timer has already expired when cancel_one() is called, then + * the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t cancel_one() + { + boost::system::error_code ec; + std::size_t s = this->service.cancel_one(this->implementation, ec); + boost::asio::detail::throw_error(ec, "cancel_one"); + return s; + } + + /// Cancels one asynchronous operation that is waiting on the timer. + /** + * This function forces the completion of one pending asynchronous wait + * operation against the timer. Handlers are cancelled in FIFO order. The + * handler for the cancelled operation will be invoked with the + * boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. That is, + * either 0 or 1. + * + * @note If the timer has already expired when cancel_one() is called, then + * the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t cancel_one(boost::system::error_code& ec) + { + return this->service.cancel_one(this->implementation, ec); + } + + /// Get the timer's expiry time as an absolute time. + /** + * This function may be used to obtain the timer's current expiry time. + * Whether the timer has expired or not does not affect this value. + */ + time_type expires_at() const + { + return this->service.expires_at(this->implementation); + } + + /// Set the timer's expiry time as an absolute time. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @return The number of asynchronous operations that were cancelled. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note If the timer has already expired when expires_at() is called, then + * the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t expires_at(const time_type& expiry_time) + { + boost::system::error_code ec; + std::size_t s = this->service.expires_at( + this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_at"); + return s; + } + + /// Set the timer's expiry time as an absolute time. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. + * + * @note If the timer has already expired when expires_at() is called, then + * the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t expires_at(const time_type& expiry_time, + boost::system::error_code& ec) + { + return this->service.expires_at(this->implementation, expiry_time, ec); + } + + /// Get the timer's expiry time relative to now. + /** + * This function may be used to obtain the timer's current expiry time. + * Whether the timer has expired or not does not affect this value. + */ + duration_type expires_from_now() const + { + return this->service.expires_from_now(this->implementation); + } + + /// Set the timer's expiry time relative to now. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @return The number of asynchronous operations that were cancelled. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note If the timer has already expired when expires_from_now() is called, + * then the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t expires_from_now(const duration_type& expiry_time) + { + boost::system::error_code ec; + std::size_t s = this->service.expires_from_now( + this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_from_now"); + return s; + } + + /// Set the timer's expiry time relative to now. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. + * + * @note If the timer has already expired when expires_from_now() is called, + * then the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t expires_from_now(const duration_type& expiry_time, + boost::system::error_code& ec) + { + return this->service.expires_from_now( + this->implementation, expiry_time, ec); + } + + /// Perform a blocking wait on the timer. + /** + * This function is used to wait for the timer to expire. This function + * blocks and does not return until the timer has expired. + * + * @throws boost::system::system_error Thrown on failure. + */ + void wait() + { + boost::system::error_code ec; + this->service.wait(this->implementation, ec); + boost::asio::detail::throw_error(ec, "wait"); + } + + /// Perform a blocking wait on the timer. + /** + * This function is used to wait for the timer to expire. This function + * blocks and does not return until the timer has expired. + * + * @param ec Set to indicate what error occurred, if any. + */ + void wait(boost::system::error_code& ec) + { + this->service.wait(this->implementation, ec); + } + + /// Start an asynchronous wait on the timer. + /** + * This function may be used to initiate an asynchronous wait against the + * timer. It always returns immediately. + * + * For each call to async_wait(), the supplied handler will be called exactly + * once. The handler will be called when: + * + * @li The timer has expired. + * + * @li The timer was cancelled, in which case the handler is passed the error + * code boost::asio::error::operation_aborted. + * + * @param handler The handler to be called when the timer expires. Copies + * will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template <typename WaitHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, + void (boost::system::error_code)) + async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WaitHandler. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + return this->service.async_wait(this->implementation, + BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) + // || defined(GENERATING_DOCUMENTATION) + +#endif // BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP
diff --git a/boost/boost/asio/basic_io_object.hpp b/boost/boost/asio/basic_io_object.hpp new file mode 100644 index 0000000..568ec6a --- /dev/null +++ b/boost/boost/asio/basic_io_object.hpp
@@ -0,0 +1,242 @@ +// +// basic_io_object.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_IO_OBJECT_HPP +#define BOOST_ASIO_BASIC_IO_OBJECT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/io_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +#if defined(BOOST_ASIO_HAS_MOVE) +namespace detail +{ + // Type trait used to determine whether a service supports move. + template <typename IoObjectService> + class service_has_move + { + private: + typedef IoObjectService service_type; + typedef typename service_type::implementation_type implementation_type; + + template <typename T, typename U> + static auto eval(T* t, U* u) -> decltype(t->move_construct(*u, *u), char()); + static char (&eval(...))[2]; + + public: + static const bool value = + sizeof(service_has_move::eval( + static_cast<service_type*>(0), + static_cast<implementation_type*>(0))) == 1; + }; +} +#endif // defined(BOOST_ASIO_HAS_MOVE) + +/// Base class for all I/O objects. +/** + * @note All I/O objects are non-copyable. However, when using C++0x, certain + * I/O objects do support move construction and move assignment. + */ +#if !defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) +template <typename IoObjectService> +#else +template <typename IoObjectService, + bool Movable = detail::service_has_move<IoObjectService>::value> +#endif +class basic_io_object +{ +public: + /// The type of the service that will be used to provide I/O operations. + typedef IoObjectService service_type; + + /// The underlying implementation type of I/O object. + typedef typename service_type::implementation_type implementation_type; + + /// Get the io_service associated with the object. + /** + * This function may be used to obtain the io_service object that the I/O + * object uses to dispatch handlers for asynchronous operations. + * + * @return A reference to the io_service object that the I/O object will use + * to dispatch handlers. Ownership is not transferred to the caller. + */ + boost::asio::io_service& get_io_service() + { + return service.get_io_service(); + } + +protected: + /// Construct a basic_io_object. + /** + * Performs: + * @code get_service().construct(get_implementation()); @endcode + */ + explicit basic_io_object(boost::asio::io_service& io_service) + : service(boost::asio::use_service<IoObjectService>(io_service)) + { + service.construct(implementation); + } + +#if defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_io_object. + /** + * Performs: + * @code get_service().move_construct( + * get_implementation(), other.get_implementation()); @endcode + * + * @note Available only for services that support movability, + */ + basic_io_object(basic_io_object&& other); + + /// Move-assign a basic_io_object. + /** + * Performs: + * @code get_service().move_assign(get_implementation(), + * other.get_service(), other.get_implementation()); @endcode + * + * @note Available only for services that support movability, + */ + basic_io_object& operator=(basic_io_object&& other); +#endif // defined(GENERATING_DOCUMENTATION) + + /// Protected destructor to prevent deletion through this type. + /** + * Performs: + * @code get_service().destroy(get_implementation()); @endcode + */ + ~basic_io_object() + { + service.destroy(implementation); + } + + /// Get the service associated with the I/O object. + service_type& get_service() + { + return service; + } + + /// Get the service associated with the I/O object. + const service_type& get_service() const + { + return service; + } + + /// (Deprecated: Use get_service().) The service associated with the I/O + /// object. + /** + * @note Available only for services that do not support movability. + */ + service_type& service; + + /// Get the underlying implementation of the I/O object. + implementation_type& get_implementation() + { + return implementation; + } + + /// Get the underlying implementation of the I/O object. + const implementation_type& get_implementation() const + { + return implementation; + } + + /// (Deprecated: Use get_implementation().) The underlying implementation of + /// the I/O object. + implementation_type implementation; + +private: + basic_io_object(const basic_io_object&); + basic_io_object& operator=(const basic_io_object&); +}; + +#if defined(BOOST_ASIO_HAS_MOVE) +// Specialisation for movable objects. +template <typename IoObjectService> +class basic_io_object<IoObjectService, true> +{ +public: + typedef IoObjectService service_type; + typedef typename service_type::implementation_type implementation_type; + + boost::asio::io_service& get_io_service() + { + return service_->get_io_service(); + } + +protected: + explicit basic_io_object(boost::asio::io_service& io_service) + : service_(&boost::asio::use_service<IoObjectService>(io_service)) + { + service_->construct(implementation); + } + + basic_io_object(basic_io_object&& other) + : service_(&other.get_service()) + { + service_->move_construct(implementation, other.implementation); + } + + ~basic_io_object() + { + service_->destroy(implementation); + } + + basic_io_object& operator=(basic_io_object&& other) + { + service_->move_assign(implementation, + *other.service_, other.implementation); + service_ = other.service_; + return *this; + } + + service_type& get_service() + { + return *service_; + } + + const service_type& get_service() const + { + return *service_; + } + + implementation_type& get_implementation() + { + return implementation; + } + + const implementation_type& get_implementation() const + { + return implementation; + } + + implementation_type implementation; + +private: + basic_io_object(const basic_io_object&); + void operator=(const basic_io_object&); + + IoObjectService* service_; +}; +#endif // defined(BOOST_ASIO_HAS_MOVE) + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BASIC_IO_OBJECT_HPP
diff --git a/boost/boost/asio/basic_raw_socket.hpp b/boost/boost/asio/basic_raw_socket.hpp new file mode 100644 index 0000000..1f12827 --- /dev/null +++ b/boost/boost/asio/basic_raw_socket.hpp
@@ -0,0 +1,942 @@ +// +// basic_raw_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_RAW_SOCKET_HPP +#define BOOST_ASIO_BASIC_RAW_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/basic_socket.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/raw_socket_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides raw-oriented socket functionality. +/** + * The basic_raw_socket class template provides asynchronous and blocking + * raw-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename Protocol, + typename RawSocketService = raw_socket_service<Protocol> > +class basic_raw_socket + : public basic_socket<Protocol, RawSocketService> +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of a + /// socket. + typedef typename RawSocketService::native_handle_type native_type; + + /// The native representation of a socket. + typedef typename RawSocketService::native_handle_type native_handle_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_raw_socket without opening it. + /** + * This constructor creates a raw socket without opening it. The open() + * function must be called before data can be sent or received on the socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + */ + explicit basic_raw_socket(boost::asio::io_service& io_service) + : basic_socket<Protocol, RawSocketService>(io_service) + { + } + + /// Construct and open a basic_raw_socket. + /** + * This constructor creates and opens a raw socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket<Protocol, RawSocketService>(io_service, protocol) + { + } + + /// Construct a basic_raw_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a raw socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param endpoint An endpoint on the local machine to which the raw + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket<Protocol, RawSocketService>(io_service, endpoint) + { + } + + /// Construct a basic_raw_socket on an existing native socket. + /** + * This constructor creates a raw socket object to hold an existing + * native socket. + * + * @param io_service The io_service object that the raw socket will use + * to dispatch handlers for any asynchronous operations performed on the + * socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_raw_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_handle_type& native_socket) + : basic_socket<Protocol, RawSocketService>( + io_service, protocol, native_socket) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_raw_socket from another. + /** + * This constructor moves a raw socket from one object to another. + * + * @param other The other basic_raw_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_raw_socket(io_service&) constructor. + */ + basic_raw_socket(basic_raw_socket&& other) + : basic_socket<Protocol, RawSocketService>( + BOOST_ASIO_MOVE_CAST(basic_raw_socket)(other)) + { + } + + /// Move-assign a basic_raw_socket from another. + /** + * This assignment operator moves a raw socket from one object to another. + * + * @param other The other basic_raw_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_raw_socket(io_service&) constructor. + */ + basic_raw_socket& operator=(basic_raw_socket&& other) + { + basic_socket<Protocol, RawSocketService>::operator=( + BOOST_ASIO_MOVE_CAST(basic_raw_socket)(other)); + return *this; + } + + /// Move-construct a basic_raw_socket from a socket of another protocol type. + /** + * This constructor moves a raw socket from one object to another. + * + * @param other The other basic_raw_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_raw_socket(io_service&) constructor. + */ + template <typename Protocol1, typename RawSocketService1> + basic_raw_socket(basic_raw_socket<Protocol1, RawSocketService1>&& other, + typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) + : basic_socket<Protocol, RawSocketService>( + BOOST_ASIO_MOVE_CAST2(basic_raw_socket< + Protocol1, RawSocketService1>)(other)) + { + } + + /// Move-assign a basic_raw_socket from a socket of another protocol type. + /** + * This assignment operator moves a raw socket from one object to another. + * + * @param other The other basic_raw_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_raw_socket(io_service&) constructor. + */ + template <typename Protocol1, typename RawSocketService1> + typename enable_if<is_convertible<Protocol1, Protocol>::value, + basic_raw_socket>::type& operator=( + basic_raw_socket<Protocol1, RawSocketService1>&& other) + { + basic_socket<Protocol, RawSocketService>::operator=( + BOOST_ASIO_MOVE_CAST2(basic_raw_socket< + Protocol1, RawSocketService1>)(other)); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code socket.send(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One ore more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + * + * @note The send operation can only be used with a connected socket. Use + * the send_to function to send data on an unconnected raw socket. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->get_service().send( + this->get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected raw + * socket. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send(this->get_implementation(), + buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Start an asynchronous send on a connected socket. + /** + * This function is used to send data on the raw socket. The function call + * will block until the data has been sent successfully or an error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_send operation can only be used with a connected socket. + * Use the async_send_to function to send data on an unconnected raw + * socket. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send(this->get_implementation(), + buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.send_to(boost::asio::buffer(data, size), destination); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send_to( + this->get_implementation(), buffers, destination, 0, ec); + boost::asio::detail::throw_error(ec, "send_to"); + return s; + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename ConstBufferSequence> + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send_to( + this->get_implementation(), buffers, destination, flags, ec); + boost::asio::detail::throw_error(ec, "send_to"); + return s; + } + + /// Send raw data to the specified endpoint. + /** + * This function is used to send raw data to the specified remote endpoint. + * The function call will block until the data has been sent successfully or + * an error occurs. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * + * @param destination The remote endpoint to which the data will be sent. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. + */ + template <typename ConstBufferSequence> + std::size_t send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->get_service().send_to(this->get_implementation(), + buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send raw data to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * boost::asio::ip::udp::endpoint destination( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_send_to( + * boost::asio::buffer(data, size), destination, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send_to(this->get_implementation(), + buffers, destination, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send raw data to the specified + * remote endpoint. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent to the remote endpoint. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param destination The remote endpoint to which the data will be sent. + * Copies will be made of the endpoint as required. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send_to(const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send_to( + this->get_implementation(), buffers, destination, flags, + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.receive(boost::asio::buffer(data, size)); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the raw socket. The function + * call will block until data has been received successfully or an error + * occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + * + * @note The receive operation can only be used with a connected socket. Use + * the receive_from function to receive data on an unconnected raw + * socket. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->get_service().receive( + this->get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the raw + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * raw socket. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Start an asynchronous receive on a connected socket. + /** + * This function is used to asynchronously receive data from the raw + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The async_receive operation can only be used with a connected socket. + * Use the async_receive_from function to receive data on an unconnected + * raw socket. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * boost::asio::ip::udp::endpoint sender_endpoint; + * socket.receive_from( + * boost::asio::buffer(data, size), sender_endpoint); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive_from( + this->get_implementation(), buffers, sender_endpoint, 0, ec); + boost::asio::detail::throw_error(ec, "receive_from"); + return s; + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. + */ + template <typename MutableBufferSequence> + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive_from( + this->get_implementation(), buffers, sender_endpoint, flags, ec); + boost::asio::detail::throw_error(ec, "receive_from"); + return s; + } + + /// Receive raw data with the endpoint of the sender. + /** + * This function is used to receive raw data. The function call will block + * until data has been received successfully or an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. + */ + template <typename MutableBufferSequence> + std::size_t receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + boost::system::error_code& ec) + { + return this->get_service().receive_from(this->get_implementation(), + buffers, sender_endpoint, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive raw data. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code socket.async_receive_from( + * boost::asio::buffer(data, size), 0, sender_endpoint, handler); @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive_from( + this->get_implementation(), buffers, sender_endpoint, 0, + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive raw data. The function + * call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param sender_endpoint An endpoint object that receives the endpoint of + * the remote sender of the data. Ownership of the sender_endpoint object + * is retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive_from(const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive_from( + this->get_implementation(), buffers, sender_endpoint, flags, + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BASIC_RAW_SOCKET_HPP
diff --git a/boost/boost/asio/basic_seq_packet_socket.hpp b/boost/boost/asio/basic_seq_packet_socket.hpp new file mode 100644 index 0000000..5a7d920 --- /dev/null +++ b/boost/boost/asio/basic_seq_packet_socket.hpp
@@ -0,0 +1,567 @@ +// +// basic_seq_packet_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP +#define BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/basic_socket.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/seq_packet_socket_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides sequenced packet socket functionality. +/** + * The basic_seq_packet_socket class template provides asynchronous and blocking + * sequenced packet socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename Protocol, + typename SeqPacketSocketService = seq_packet_socket_service<Protocol> > +class basic_seq_packet_socket + : public basic_socket<Protocol, SeqPacketSocketService> +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of a + /// socket. + typedef typename SeqPacketSocketService::native_handle_type native_type; + + /// The native representation of a socket. + typedef typename SeqPacketSocketService::native_handle_type + native_handle_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_seq_packet_socket without opening it. + /** + * This constructor creates a sequenced packet socket without opening it. The + * socket needs to be opened and then connected or accepted before data can + * be sent or received on it. + * + * @param io_service The io_service object that the sequenced packet socket + * will use to dispatch handlers for any asynchronous operations performed on + * the socket. + */ + explicit basic_seq_packet_socket(boost::asio::io_service& io_service) + : basic_socket<Protocol, SeqPacketSocketService>(io_service) + { + } + + /// Construct and open a basic_seq_packet_socket. + /** + * This constructor creates and opens a sequenced_packet socket. The socket + * needs to be connected or accepted before data can be sent or received on + * it. + * + * @param io_service The io_service object that the sequenced packet socket + * will use to dispatch handlers for any asynchronous operations performed on + * the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_seq_packet_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket<Protocol, SeqPacketSocketService>(io_service, protocol) + { + } + + /// Construct a basic_seq_packet_socket, opening it and binding it to the + /// given local endpoint. + /** + * This constructor creates a sequenced packet socket and automatically opens + * it bound to the specified endpoint on the local machine. The protocol used + * is the protocol associated with the given endpoint. + * + * @param io_service The io_service object that the sequenced packet socket + * will use to dispatch handlers for any asynchronous operations performed on + * the socket. + * + * @param endpoint An endpoint on the local machine to which the sequenced + * packet socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_seq_packet_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket<Protocol, SeqPacketSocketService>(io_service, endpoint) + { + } + + /// Construct a basic_seq_packet_socket on an existing native socket. + /** + * This constructor creates a sequenced packet socket object to hold an + * existing native socket. + * + * @param io_service The io_service object that the sequenced packet socket + * will use to dispatch handlers for any asynchronous operations performed on + * the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_seq_packet_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_handle_type& native_socket) + : basic_socket<Protocol, SeqPacketSocketService>( + io_service, protocol, native_socket) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_seq_packet_socket from another. + /** + * This constructor moves a sequenced packet socket from one object to + * another. + * + * @param other The other basic_seq_packet_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_seq_packet_socket(io_service&) constructor. + */ + basic_seq_packet_socket(basic_seq_packet_socket&& other) + : basic_socket<Protocol, SeqPacketSocketService>( + BOOST_ASIO_MOVE_CAST(basic_seq_packet_socket)(other)) + { + } + + /// Move-assign a basic_seq_packet_socket from another. + /** + * This assignment operator moves a sequenced packet socket from one object to + * another. + * + * @param other The other basic_seq_packet_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_seq_packet_socket(io_service&) constructor. + */ + basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other) + { + basic_socket<Protocol, SeqPacketSocketService>::operator=( + BOOST_ASIO_MOVE_CAST(basic_seq_packet_socket)(other)); + return *this; + } + + /// Move-construct a basic_seq_packet_socket from a socket of another protocol + /// type. + /** + * This constructor moves a sequenced packet socket from one object to + * another. + * + * @param other The other basic_seq_packet_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_seq_packet_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SeqPacketSocketService1> + basic_seq_packet_socket( + basic_seq_packet_socket<Protocol1, SeqPacketSocketService1>&& other, + typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) + : basic_socket<Protocol, SeqPacketSocketService>( + BOOST_ASIO_MOVE_CAST2(basic_seq_packet_socket< + Protocol1, SeqPacketSocketService1>)(other)) + { + } + + /// Move-assign a basic_seq_packet_socket from a socket of another protocol + /// type. + /** + * This assignment operator moves a sequenced packet socket from one object to + * another. + * + * @param other The other basic_seq_packet_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_seq_packet_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SeqPacketSocketService1> + typename enable_if<is_convertible<Protocol1, Protocol>::value, + basic_seq_packet_socket>::type& operator=( + basic_seq_packet_socket<Protocol1, SeqPacketSocketService1>&& other) + { + basic_socket<Protocol, SeqPacketSocketService>::operator=( + BOOST_ASIO_MOVE_CAST2(basic_seq_packet_socket< + Protocol1, SeqPacketSocketService1>)(other)); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Send some data on the socket. + /** + * This function is used to send data on the sequenced packet socket. The + * function call will block until the data has been sent successfully, or an + * until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.send(boost::asio::buffer(data, size), 0); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the sequenced packet socket. The + * function call will block the data has been sent successfully, or an until + * error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. Returns 0 if an error occurred. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->get_service().send( + this->get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send data on the sequenced packet + * socket. The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), 0, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send(this->get_implementation(), + buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the sequenced packet socket. The + * function call will block until data has been received successfully, or + * until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param out_flags After the receive call completes, contains flags + * associated with the received data. For example, if the + * socket_base::message_end_of_record bit is set then the received data marks + * the end of a record. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(boost::asio::buffer(data, size), out_flags); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags& out_flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, 0, out_flags, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the sequenced packet socket. The + * function call will block until data has been received successfully, or + * until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param in_flags Flags specifying how the receive call is to be made. + * + * @param out_flags After the receive call completes, contains flags + * associated with the received data. For example, if the + * socket_base::message_end_of_record bit is set then the received data marks + * the end of a record. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(boost::asio::buffer(data, size), 0, out_flags); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags in_flags, + socket_base::message_flags& out_flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, in_flags, out_flags, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the sequenced packet socket. The + * function call will block until data has been received successfully, or + * until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param in_flags Flags specifying how the receive call is to be made. + * + * @param out_flags After the receive call completes, contains flags + * associated with the received data. For example, if the + * socket_base::message_end_of_record bit is set then the received data marks + * the end of a record. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. Returns 0 if an error occurred. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, boost::system::error_code& ec) + { + return this->get_service().receive(this->get_implementation(), + buffers, in_flags, out_flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the sequenced + * packet socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param out_flags Once the asynchronous operation completes, contains flags + * associated with the received data. For example, if the + * socket_base::message_end_of_record bit is set then the received data marks + * the end of a record. The caller must guarantee that the referenced + * variable remains valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), out_flags, handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags& out_flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive( + this->get_implementation(), buffers, 0, out_flags, + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the sequenced + * data socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param in_flags Flags specifying how the receive call is to be made. + * + * @param out_flags Once the asynchronous operation completes, contains flags + * associated with the received data. For example, if the + * socket_base::message_end_of_record bit is set then the received data marks + * the end of a record. The caller must guarantee that the referenced + * variable remains valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive( + * boost::asio::buffer(data, size), + * 0, out_flags, handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive( + this->get_implementation(), buffers, in_flags, out_flags, + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BASIC_SEQ_PACKET_SOCKET_HPP
diff --git a/boost/boost/asio/basic_serial_port.hpp b/boost/boost/asio/basic_serial_port.hpp new file mode 100644 index 0000000..e0f83b0 --- /dev/null +++ b/boost/boost/asio/basic_serial_port.hpp
@@ -0,0 +1,697 @@ +// +// basic_serial_port.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SERIAL_PORT_HPP +#define BOOST_ASIO_BASIC_SERIAL_PORT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \ + || defined(GENERATING_DOCUMENTATION) + +#include <string> +#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/serial_port_base.hpp> +#include <boost/asio/serial_port_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides serial port functionality. +/** + * The basic_serial_port class template provides functionality that is common + * to all serial ports. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename SerialPortService = serial_port_service> +class basic_serial_port + : public basic_io_object<SerialPortService>, + public serial_port_base +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of a + /// serial port. + typedef typename SerialPortService::native_handle_type native_type; + + /// The native representation of a serial port. + typedef typename SerialPortService::native_handle_type native_handle_type; + + /// A basic_serial_port is always the lowest layer. + typedef basic_serial_port<SerialPortService> lowest_layer_type; + + /// Construct a basic_serial_port without opening it. + /** + * This constructor creates a serial port without opening it. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + */ + explicit basic_serial_port(boost::asio::io_service& io_service) + : basic_io_object<SerialPortService>(io_service) + { + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param device The platform-specific device name for this serial + * port. + */ + explicit basic_serial_port(boost::asio::io_service& io_service, + const char* device) + : basic_io_object<SerialPortService>(io_service) + { + boost::system::error_code ec; + this->get_service().open(this->get_implementation(), device, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_serial_port. + /** + * This constructor creates and opens a serial port for the specified device + * name. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param device The platform-specific device name for this serial + * port. + */ + explicit basic_serial_port(boost::asio::io_service& io_service, + const std::string& device) + : basic_io_object<SerialPortService>(io_service) + { + boost::system::error_code ec; + this->get_service().open(this->get_implementation(), device, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct a basic_serial_port on an existing native serial port. + /** + * This constructor creates a serial port object to hold an existing native + * serial port. + * + * @param io_service The io_service object that the serial port will use to + * dispatch handlers for any asynchronous operations performed on the port. + * + * @param native_serial_port A native serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_serial_port(boost::asio::io_service& io_service, + const native_handle_type& native_serial_port) + : basic_io_object<SerialPortService>(io_service) + { + boost::system::error_code ec; + this->get_service().assign(this->get_implementation(), + native_serial_port, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_serial_port from another. + /** + * This constructor moves a serial port from one object to another. + * + * @param other The other basic_serial_port object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_serial_port(io_service&) constructor. + */ + basic_serial_port(basic_serial_port&& other) + : basic_io_object<SerialPortService>( + BOOST_ASIO_MOVE_CAST(basic_serial_port)(other)) + { + } + + /// Move-assign a basic_serial_port from another. + /** + * This assignment operator moves a serial port from one object to another. + * + * @param other The other basic_serial_port object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_serial_port(io_service&) constructor. + */ + basic_serial_port& operator=(basic_serial_port&& other) + { + basic_io_object<SerialPortService>::operator=( + BOOST_ASIO_MOVE_CAST(basic_serial_port)(other)); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_serial_port cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Get a const reference to the lowest layer. + /** + * This function returns a const reference to the lowest layer in a stack of + * layers. Since a basic_serial_port cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A const reference to the lowest layer in the stack of layers. + * Ownership is not transferred to the caller. + */ + const lowest_layer_type& lowest_layer() const + { + return *this; + } + + /// Open the serial port using the specified device name. + /** + * This function opens the serial port for the specified device name. + * + * @param device The platform-specific device name. + * + * @throws boost::system::system_error Thrown on failure. + */ + void open(const std::string& device) + { + boost::system::error_code ec; + this->get_service().open(this->get_implementation(), device, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Open the serial port using the specified device name. + /** + * This function opens the serial port using the given platform-specific + * device name. + * + * @param device The platform-specific device name. + * + * @param ec Set the indicate what error occurred, if any. + */ + boost::system::error_code open(const std::string& device, + boost::system::error_code& ec) + { + return this->get_service().open(this->get_implementation(), device, ec); + } + + /// Assign an existing native serial port to the serial port. + /* + * This function opens the serial port to hold an existing native serial port. + * + * @param native_serial_port A native serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const native_handle_type& native_serial_port) + { + boost::system::error_code ec; + this->get_service().assign(this->get_implementation(), + native_serial_port, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native serial port to the serial port. + /* + * This function opens the serial port to hold an existing native serial port. + * + * @param native_serial_port A native serial port. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const native_handle_type& native_serial_port, + boost::system::error_code& ec) + { + return this->get_service().assign(this->get_implementation(), + native_serial_port, ec); + } + + /// Determine whether the serial port is open. + bool is_open() const + { + return this->get_service().is_open(this->get_implementation()); + } + + /// Close the serial port. + /** + * This function is used to close the serial port. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + this->get_service().close(this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "close"); + } + + /// Close the serial port. + /** + * This function is used to close the serial port. Any asynchronous read or + * write operations will be cancelled immediately, and will complete with the + * boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->get_service().close(this->get_implementation(), ec); + } + + /// (Deprecated: Use native_handle().) Get the native serial port + /// representation. + /** + * This function may be used to obtain the underlying representation of the + * serial port. This is intended to allow access to native serial port + * functionality that is not otherwise provided. + */ + native_type native() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Get the native serial port representation. + /** + * This function may be used to obtain the underlying representation of the + * serial port. This is intended to allow access to native serial port + * functionality that is not otherwise provided. + */ + native_handle_type native_handle() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Cancel all asynchronous operations associated with the serial port. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + this->get_service().cancel(this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the serial port. + /** + * This function causes all outstanding asynchronous read or write operations + * to finish immediately, and the handlers for cancelled operations will be + * passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->get_service().cancel(this->get_implementation(), ec); + } + + /// Send a break sequence to the serial port. + /** + * This function causes a break sequence of platform-specific duration to be + * sent out the serial port. + * + * @throws boost::system::system_error Thrown on failure. + */ + void send_break() + { + boost::system::error_code ec; + this->get_service().send_break(this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "send_break"); + } + + /// Send a break sequence to the serial port. + /** + * This function causes a break sequence of platform-specific duration to be + * sent out the serial port. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code send_break(boost::system::error_code& ec) + { + return this->get_service().send_break(this->get_implementation(), ec); + } + + /// Set an option on the serial port. + /** + * This function is used to set an option on the serial port. + * + * @param option The option value to be set on the serial port. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template <typename SettableSerialPortOption> + void set_option(const SettableSerialPortOption& option) + { + boost::system::error_code ec; + this->get_service().set_option(this->get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + + /// Set an option on the serial port. + /** + * This function is used to set an option on the serial port. + * + * @param option The option value to be set on the serial port. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template <typename SettableSerialPortOption> + boost::system::error_code set_option(const SettableSerialPortOption& option, + boost::system::error_code& ec) + { + return this->get_service().set_option( + this->get_implementation(), option, ec); + } + + /// Get an option from the serial port. + /** + * This function is used to get the current value of an option on the serial + * port. + * + * @param option The option value to be obtained from the serial port. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template <typename GettableSerialPortOption> + void get_option(GettableSerialPortOption& option) + { + boost::system::error_code ec; + this->get_service().get_option(this->get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "get_option"); + } + + /// Get an option from the serial port. + /** + * This function is used to get the current value of an option on the serial + * port. + * + * @param option The option value to be obtained from the serial port. + * + * @param ec Set to indicate what error occured, if any. + * + * @sa GettableSerialPortOption @n + * boost::asio::serial_port_base::baud_rate @n + * boost::asio::serial_port_base::flow_control @n + * boost::asio::serial_port_base::parity @n + * boost::asio::serial_port_base::stop_bits @n + * boost::asio::serial_port_base::character_size + */ + template <typename GettableSerialPortOption> + boost::system::error_code get_option(GettableSerialPortOption& option, + boost::system::error_code& ec) + { + return this->get_service().get_option( + this->get_implementation(), option, ec); + } + + /// Write some data to the serial port. + /** + * This function is used to write data to the serial port. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the serial port. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().write_some( + this->get_implementation(), buffers, ec); + boost::asio::detail::throw_error(ec, "write_some"); + return s; + } + + /// Write some data to the serial port. + /** + * This function is used to write data to the serial port. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the serial port. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->get_service().write_some( + this->get_implementation(), buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the serial port. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the serial port. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_write_some(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_write_some(this->get_implementation(), + buffers, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Read some data from the serial port. + /** + * This function is used to read data from the serial port. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().read_some( + this->get_implementation(), buffers, ec); + boost::asio::detail::throw_error(ec, "read_some"); + return s; + } + + /// Read some data from the serial port. + /** + * This function is used to read data from the serial port. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->get_service().read_some( + this->get_implementation(), buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the serial port. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * serial_port.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_read_some(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_read_some(this->get_implementation(), + buffers, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) + // || defined(GENERATING_DOCUMENTATION) + +#endif // BOOST_ASIO_BASIC_SERIAL_PORT_HPP
diff --git a/boost/boost/asio/basic_signal_set.hpp b/boost/boost/asio/basic_signal_set.hpp new file mode 100644 index 0000000..48e28ca --- /dev/null +++ b/boost/boost/asio/basic_signal_set.hpp
@@ -0,0 +1,386 @@ +// +// basic_signal_set.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SIGNAL_SET_HPP +#define BOOST_ASIO_BASIC_SIGNAL_SET_HPP + +#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/basic_io_object.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/signal_set_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides signal functionality. +/** + * The basic_signal_set class template provides the ability to perform an + * asynchronous wait for one or more signals to occur. + * + * Most applications will use the boost::asio::signal_set typedef. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Example + * Performing an asynchronous wait: + * @code + * void handler( + * const boost::system::error_code& error, + * int signal_number) + * { + * if (!error) + * { + * // A signal occurred. + * } + * } + * + * ... + * + * // Construct a signal set registered for process termination. + * boost::asio::signal_set signals(io_service, SIGINT, SIGTERM); + * + * // Start an asynchronous wait for one of the signals to occur. + * signals.async_wait(handler); + * @endcode + * + * @par Queueing of signal notifications + * + * If a signal is registered with a signal_set, and the signal occurs when + * there are no waiting handlers, then the signal notification is queued. The + * next async_wait operation on that signal_set will dequeue the notification. + * If multiple notifications are queued, subsequent async_wait operations + * dequeue them one at a time. Signal notifications are dequeued in order of + * ascending signal number. + * + * If a signal number is removed from a signal_set (using the @c remove or @c + * erase member functions) then any queued notifications for that signal are + * discarded. + * + * @par Multiple registration of signals + * + * The same signal number may be registered with different signal_set objects. + * When the signal occurs, one handler is called for each signal_set object. + * + * Note that multiple registration only works for signals that are registered + * using Asio. The application must not also register a signal handler using + * functions such as @c signal() or @c sigaction(). + * + * @par Signal masking on POSIX platforms + * + * POSIX allows signals to be blocked using functions such as @c sigprocmask() + * and @c pthread_sigmask(). For signals to be delivered, programs must ensure + * that any signals registered using signal_set objects are unblocked in at + * least one thread. + */ +template <typename SignalSetService = signal_set_service> +class basic_signal_set + : public basic_io_object<SignalSetService> +{ +public: + /// Construct a signal set without adding any signals. + /** + * This constructor creates a signal set without registering for any signals. + * + * @param io_service The io_service object that the signal set will use to + * dispatch handlers for any asynchronous operations performed on the set. + */ + explicit basic_signal_set(boost::asio::io_service& io_service) + : basic_io_object<SignalSetService>(io_service) + { + } + + /// Construct a signal set and add one signal. + /** + * This constructor creates a signal set and registers for one signal. + * + * @param io_service The io_service object that the signal set will use to + * dispatch handlers for any asynchronous operations performed on the set. + * + * @param signal_number_1 The signal number to be added. + * + * @note This constructor is equivalent to performing: + * @code boost::asio::signal_set signals(io_service); + * signals.add(signal_number_1); @endcode + */ + basic_signal_set(boost::asio::io_service& io_service, int signal_number_1) + : basic_io_object<SignalSetService>(io_service) + { + boost::system::error_code ec; + this->service.add(this->implementation, signal_number_1, ec); + boost::asio::detail::throw_error(ec, "add"); + } + + /// Construct a signal set and add two signals. + /** + * This constructor creates a signal set and registers for two signals. + * + * @param io_service The io_service object that the signal set will use to + * dispatch handlers for any asynchronous operations performed on the set. + * + * @param signal_number_1 The first signal number to be added. + * + * @param signal_number_2 The second signal number to be added. + * + * @note This constructor is equivalent to performing: + * @code boost::asio::signal_set signals(io_service); + * signals.add(signal_number_1); + * signals.add(signal_number_2); @endcode + */ + basic_signal_set(boost::asio::io_service& io_service, int signal_number_1, + int signal_number_2) + : basic_io_object<SignalSetService>(io_service) + { + boost::system::error_code ec; + this->service.add(this->implementation, signal_number_1, ec); + boost::asio::detail::throw_error(ec, "add"); + this->service.add(this->implementation, signal_number_2, ec); + boost::asio::detail::throw_error(ec, "add"); + } + + /// Construct a signal set and add three signals. + /** + * This constructor creates a signal set and registers for three signals. + * + * @param io_service The io_service object that the signal set will use to + * dispatch handlers for any asynchronous operations performed on the set. + * + * @param signal_number_1 The first signal number to be added. + * + * @param signal_number_2 The second signal number to be added. + * + * @param signal_number_3 The third signal number to be added. + * + * @note This constructor is equivalent to performing: + * @code boost::asio::signal_set signals(io_service); + * signals.add(signal_number_1); + * signals.add(signal_number_2); + * signals.add(signal_number_3); @endcode + */ + basic_signal_set(boost::asio::io_service& io_service, int signal_number_1, + int signal_number_2, int signal_number_3) + : basic_io_object<SignalSetService>(io_service) + { + boost::system::error_code ec; + this->service.add(this->implementation, signal_number_1, ec); + boost::asio::detail::throw_error(ec, "add"); + this->service.add(this->implementation, signal_number_2, ec); + boost::asio::detail::throw_error(ec, "add"); + this->service.add(this->implementation, signal_number_3, ec); + boost::asio::detail::throw_error(ec, "add"); + } + + /// Add a signal to a signal_set. + /** + * This function adds the specified signal to the set. It has no effect if the + * signal is already in the set. + * + * @param signal_number The signal to be added to the set. + * + * @throws boost::system::system_error Thrown on failure. + */ + void add(int signal_number) + { + boost::system::error_code ec; + this->service.add(this->implementation, signal_number, ec); + boost::asio::detail::throw_error(ec, "add"); + } + + /// Add a signal to a signal_set. + /** + * This function adds the specified signal to the set. It has no effect if the + * signal is already in the set. + * + * @param signal_number The signal to be added to the set. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code add(int signal_number, + boost::system::error_code& ec) + { + return this->service.add(this->implementation, signal_number, ec); + } + + /// Remove a signal from a signal_set. + /** + * This function removes the specified signal from the set. It has no effect + * if the signal is not in the set. + * + * @param signal_number The signal to be removed from the set. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note Removes any notifications that have been queued for the specified + * signal number. + */ + void remove(int signal_number) + { + boost::system::error_code ec; + this->service.remove(this->implementation, signal_number, ec); + boost::asio::detail::throw_error(ec, "remove"); + } + + /// Remove a signal from a signal_set. + /** + * This function removes the specified signal from the set. It has no effect + * if the signal is not in the set. + * + * @param signal_number The signal to be removed from the set. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note Removes any notifications that have been queued for the specified + * signal number. + */ + boost::system::error_code remove(int signal_number, + boost::system::error_code& ec) + { + return this->service.remove(this->implementation, signal_number, ec); + } + + /// Remove all signals from a signal_set. + /** + * This function removes all signals from the set. It has no effect if the set + * is already empty. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note Removes all queued notifications. + */ + void clear() + { + boost::system::error_code ec; + this->service.clear(this->implementation, ec); + boost::asio::detail::throw_error(ec, "clear"); + } + + /// Remove all signals from a signal_set. + /** + * This function removes all signals from the set. It has no effect if the set + * is already empty. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note Removes all queued notifications. + */ + boost::system::error_code clear(boost::system::error_code& ec) + { + return this->service.clear(this->implementation, ec); + } + + /// Cancel all operations associated with the signal set. + /** + * This function forces the completion of any pending asynchronous wait + * operations against the signal set. The handler for each cancelled + * operation will be invoked with the boost::asio::error::operation_aborted + * error code. + * + * Cancellation does not alter the set of registered signals. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note If a registered signal occurred before cancel() is called, then the + * handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + void cancel() + { + boost::system::error_code ec; + this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all operations associated with the signal set. + /** + * This function forces the completion of any pending asynchronous wait + * operations against the signal set. The handler for each cancelled + * operation will be invoked with the boost::asio::error::operation_aborted + * error code. + * + * Cancellation does not alter the set of registered signals. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note If a registered signal occurred before cancel() is called, then the + * handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Start an asynchronous operation to wait for a signal to be delivered. + /** + * This function may be used to initiate an asynchronous wait against the + * signal set. It always returns immediately. + * + * For each call to async_wait(), the supplied handler will be called exactly + * once. The handler will be called when: + * + * @li One of the registered signals in the signal set occurs; or + * + * @li The signal set was cancelled, in which case the handler is passed the + * error code boost::asio::error::operation_aborted. + * + * @param handler The handler to be called when the signal occurs. Copies + * will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * int signal_number // Indicates which signal occurred. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template <typename SignalHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler, + void (boost::system::error_code, int)) + async_wait(BOOST_ASIO_MOVE_ARG(SignalHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a SignalHandler. + BOOST_ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check; + + return this->service.async_wait(this->implementation, + BOOST_ASIO_MOVE_CAST(SignalHandler)(handler)); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BASIC_SIGNAL_SET_HPP
diff --git a/boost/boost/asio/basic_socket.hpp b/boost/boost/asio/basic_socket.hpp new file mode 100644 index 0000000..7b6ac08 --- /dev/null +++ b/boost/boost/asio/basic_socket.hpp
@@ -0,0 +1,1520 @@ +// +// basic_socket.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_HPP +#define BOOST_ASIO_BASIC_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/async_result.hpp> +#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/socket_base.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides socket functionality. +/** + * The basic_socket class template provides functionality that is common to both + * stream-oriented and datagram-oriented sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename Protocol, typename SocketService> +class basic_socket + : public basic_io_object<SocketService>, + public socket_base +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of a + /// socket. + typedef typename SocketService::native_handle_type native_type; + + /// The native representation of a socket. + typedef typename SocketService::native_handle_type native_handle_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// A basic_socket is always the lowest layer. + typedef basic_socket<Protocol, SocketService> lowest_layer_type; + + /// Construct a basic_socket without opening it. + /** + * This constructor creates a socket without opening it. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_socket(boost::asio::io_service& io_service) + : basic_io_object<SocketService>(io_service) + { + } + + /// Construct and open a basic_socket. + /** + * This constructor creates and opens a socket. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_io_object<SocketService>(io_service) + { + boost::system::error_code ec; + this->get_service().open(this->get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct a basic_socket, opening it and binding it to the given local + /// endpoint. + /** + * This constructor creates a socket and automatically opens it bound to the + * specified endpoint on the local machine. The protocol used is the protocol + * associated with the given endpoint. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_io_object<SocketService>(io_service) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + this->get_service().open(this->get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + this->get_service().bind(this->get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Construct a basic_socket on an existing native socket. + /** + * This constructor creates a socket object to hold an existing native socket. + * + * @param io_service The io_service object that the socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_handle_type& native_socket) + : basic_io_object<SocketService>(io_service) + { + boost::system::error_code ec; + this->get_service().assign(this->get_implementation(), + protocol, native_socket, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_socket from another. + /** + * This constructor moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + basic_socket(basic_socket&& other) + : basic_io_object<SocketService>( + BOOST_ASIO_MOVE_CAST(basic_socket)(other)) + { + } + + /// Move-assign a basic_socket from another. + /** + * This assignment operator moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + basic_socket& operator=(basic_socket&& other) + { + basic_io_object<SocketService>::operator=( + BOOST_ASIO_MOVE_CAST(basic_socket)(other)); + return *this; + } + + // All sockets have access to each other's implementations. + template <typename Protocol1, typename SocketService1> + friend class basic_socket; + + /// Move-construct a basic_socket from a socket of another protocol type. + /** + * This constructor moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SocketService1> + basic_socket(basic_socket<Protocol1, SocketService1>&& other, + typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) + : basic_io_object<SocketService>(other.get_io_service()) + { + this->get_service().template converting_move_construct<Protocol1>( + this->get_implementation(), other.get_implementation()); + } + + /// Move-assign a basic_socket from a socket of another protocol type. + /** + * This assignment operator moves a socket from one object to another. + * + * @param other The other basic_socket object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SocketService1> + typename enable_if<is_convertible<Protocol1, Protocol>::value, + basic_socket>::type& operator=( + basic_socket<Protocol1, SocketService1>&& other) + { + basic_socket tmp(BOOST_ASIO_MOVE_CAST2(basic_socket< + Protocol1, SocketService1>)(other)); + basic_io_object<SocketService>::operator=( + BOOST_ASIO_MOVE_CAST(basic_socket)(tmp)); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_socket cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Get a const reference to the lowest layer. + /** + * This function returns a const reference to the lowest layer in a stack of + * layers. Since a basic_socket cannot contain any further layers, it simply + * returns a reference to itself. + * + * @return A const reference to the lowest layer in the stack of layers. + * Ownership is not transferred to the caller. + */ + const lowest_layer_type& lowest_layer() const + { + return *this; + } + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * socket.open(boost::asio::ip::tcp::v4()); + * @endcode + */ + void open(const protocol_type& protocol = protocol_type()) + { + boost::system::error_code ec; + this->get_service().open(this->get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Open the socket using the specified protocol. + /** + * This function opens the socket so that it will use the specified protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * boost::system::error_code ec; + * socket.open(boost::asio::ip::tcp::v4(), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code open(const protocol_type& protocol, + boost::system::error_code& ec) + { + return this->get_service().open(this->get_implementation(), protocol, ec); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const protocol_type& protocol, + const native_handle_type& native_socket) + { + boost::system::error_code ec; + this->get_service().assign(this->get_implementation(), + protocol, native_socket, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native socket to the socket. + /* + * This function opens the socket to hold an existing native socket. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_socket A native socket. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const protocol_type& protocol, + const native_handle_type& native_socket, boost::system::error_code& ec) + { + return this->get_service().assign(this->get_implementation(), + protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open() const + { + return this->get_service().is_open(this->get_implementation()); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + void close() + { + boost::system::error_code ec; + this->get_service().close(this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "close"); + } + + /// Close the socket. + /** + * This function is used to close the socket. Any asynchronous send, receive + * or connect operations will be cancelled immediately, and will complete + * with the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::system::error_code ec; + * socket.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + * + * @note For portable behaviour with respect to graceful closure of a + * connected socket, call shutdown() before closing the socket. + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->get_service().close(this->get_implementation(), ec); + } + + /// (Deprecated: Use native_handle().) Get the native socket representation. + /** + * This function may be used to obtain the underlying representation of the + * socket. This is intended to allow access to native socket functionality + * that is not otherwise provided. + */ + native_type native() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Get the native socket representation. + /** + * This function may be used to obtain the underlying representation of the + * socket. This is intended to allow access to native socket functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note Calls to cancel() will always fail with + * boost::asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * BOOST_ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(BOOST_ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + void cancel() + { + boost::system::error_code ec; + this->get_service().cancel(this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the socket. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note Calls to cancel() will always fail with + * boost::asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using one of the following + * alternatives: + * + * @li Disable asio's I/O completion port backend by defining + * BOOST_ASIO_DISABLE_IOCP. + * + * @li Use the close() function to simultaneously cancel the outstanding + * operations and close the socket. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(BOOST_ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->get_service().cancel(this->get_implementation(), ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + * + * @throws boost::system::system_error Thrown on failure. + */ + bool at_mark() const + { + boost::system::error_code ec; + bool b = this->get_service().at_mark(this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "at_mark"); + return b; + } + + /// Determine whether the socket is at the out-of-band data mark. + /** + * This function is used to check whether the socket input is currently + * positioned at the out-of-band data mark. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return A bool indicating whether the socket is at the out-of-band data + * mark. + */ + bool at_mark(boost::system::error_code& ec) const + { + return this->get_service().at_mark(this->get_implementation(), ec); + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + * + * @throws boost::system::system_error Thrown on failure. + */ + std::size_t available() const + { + boost::system::error_code ec; + std::size_t s = this->get_service().available( + this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "available"); + return s; + } + + /// Determine the number of bytes available for reading. + /** + * This function is used to determine the number of bytes that may be read + * without blocking. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of bytes that may be read without blocking, or 0 if an + * error occurs. + */ + std::size_t available(boost::system::error_code& ec) const + { + return this->get_service().available(this->get_implementation(), ec); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * socket.open(boost::asio::ip::tcp::v4()); + * socket.bind(boost::asio::ip::tcp::endpoint( + * boost::asio::ip::tcp::v4(), 12345)); + * @endcode + */ + void bind(const endpoint_type& endpoint) + { + boost::system::error_code ec; + this->get_service().bind(this->get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Bind the socket to the given local endpoint. + /** + * This function binds the socket to the specified endpoint on the local + * machine. + * + * @param endpoint An endpoint on the local machine to which the socket will + * be bound. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * socket.open(boost::asio::ip::tcp::v4()); + * boost::system::error_code ec; + * socket.bind(boost::asio::ip::tcp::endpoint( + * boost::asio::ip::tcp::v4(), 12345), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code bind(const endpoint_type& endpoint, + boost::system::error_code& ec) + { + return this->get_service().bind(this->get_implementation(), endpoint, ec); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.connect(endpoint); + * @endcode + */ + void connect(const endpoint_type& peer_endpoint) + { + boost::system::error_code ec; + if (!is_open()) + { + this->get_service().open(this->get_implementation(), + peer_endpoint.protocol(), ec); + boost::asio::detail::throw_error(ec, "connect"); + } + this->get_service().connect(this->get_implementation(), peer_endpoint, ec); + boost::asio::detail::throw_error(ec, "connect"); + } + + /// Connect the socket to the specified endpoint. + /** + * This function is used to connect a socket to the specified remote endpoint. + * The function call will block until the connection is successfully made or + * an error occurs. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * boost::system::error_code ec; + * socket.connect(endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code connect(const endpoint_type& peer_endpoint, + boost::system::error_code& ec) + { + if (!is_open()) + { + if (this->get_service().open(this->get_implementation(), + peer_endpoint.protocol(), ec)) + { + return ec; + } + } + + return this->get_service().connect( + this->get_implementation(), peer_endpoint, ec); + } + + /// Start an asynchronous connect. + /** + * This function is used to asynchronously connect a socket to the specified + * remote endpoint. The function call always returns immediately. + * + * The socket is automatically opened if it is not already open. If the + * connect fails, and the socket was automatically opened, the socket is + * not returned to the closed state. + * + * @param peer_endpoint The remote endpoint to which the socket will be + * connected. Copies will be made of the endpoint object as required. + * + * @param handler The handler to be called when the connection operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * @code + * void connect_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Connect succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint( + * boost::asio::ip::address::from_string("1.2.3.4"), 12345); + * socket.async_connect(endpoint, connect_handler); + * @endcode + */ + template <typename ConnectHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, + void (boost::system::error_code)) + async_connect(const endpoint_type& peer_endpoint, + BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ConnectHandler. + BOOST_ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check; + + if (!is_open()) + { + boost::system::error_code ec; + const protocol_type protocol = peer_endpoint.protocol(); + if (this->get_service().open(this->get_implementation(), protocol, ec)) + { + detail::async_result_init< + ConnectHandler, void (boost::system::error_code)> init( + BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); + + this->get_io_service().post( + boost::asio::detail::bind_handler( + BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE( + ConnectHandler, void (boost::system::error_code)))( + init.handler), ec)); + + return init.result.get(); + } + } + + return this->get_service().async_connect(this->get_implementation(), + peer_endpoint, BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::no_delay option(true); + * socket.set_option(option); + * @endcode + */ + template <typename SettableSocketOption> + void set_option(const SettableSocketOption& option) + { + boost::system::error_code ec; + this->get_service().set_option(this->get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + + /// Set an option on the socket. + /** + * This function is used to set an option on the socket. + * + * @param option The new option value to be set on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Setting the IPPROTO_TCP/TCP_NODELAY option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::no_delay option(true); + * boost::system::error_code ec; + * socket.set_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename SettableSocketOption> + boost::system::error_code set_option(const SettableSocketOption& option, + boost::system::error_code& ec) + { + return this->get_service().set_option( + this->get_implementation(), option, ec); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::socket::keep_alive option; + * socket.get_option(option); + * bool is_set = option.value(); + * @endcode + */ + template <typename GettableSocketOption> + void get_option(GettableSocketOption& option) const + { + boost::system::error_code ec; + this->get_service().get_option(this->get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "get_option"); + } + + /// Get an option from the socket. + /** + * This function is used to get the current value of an option on the socket. + * + * @param option The option value to be obtained from the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::broadcast @n + * boost::asio::socket_base::do_not_route @n + * boost::asio::socket_base::keep_alive @n + * boost::asio::socket_base::linger @n + * boost::asio::socket_base::receive_buffer_size @n + * boost::asio::socket_base::receive_low_watermark @n + * boost::asio::socket_base::reuse_address @n + * boost::asio::socket_base::send_buffer_size @n + * boost::asio::socket_base::send_low_watermark @n + * boost::asio::ip::multicast::join_group @n + * boost::asio::ip::multicast::leave_group @n + * boost::asio::ip::multicast::enable_loopback @n + * boost::asio::ip::multicast::outbound_interface @n + * boost::asio::ip::multicast::hops @n + * boost::asio::ip::tcp::no_delay + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::socket::keep_alive option; + * boost::system::error_code ec; + * socket.get_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * bool is_set = option.value(); + * @endcode + */ + template <typename GettableSocketOption> + boost::system::error_code get_option(GettableSocketOption& option, + boost::system::error_code& ec) const + { + return this->get_service().get_option( + this->get_implementation(), option, ec); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::bytes_readable @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::socket::bytes_readable command; + * socket.io_control(command); + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template <typename IoControlCommand> + void io_control(IoControlCommand& command) + { + boost::system::error_code ec; + this->get_service().io_control(this->get_implementation(), command, ec); + boost::asio::detail::throw_error(ec, "io_control"); + } + + /// Perform an IO control command on the socket. + /** + * This function is used to execute an IO control command on the socket. + * + * @param command The IO control command to be performed on the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::bytes_readable @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::socket::bytes_readable command; + * boost::system::error_code ec; + * socket.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * std::size_t bytes_readable = command.get(); + * @endcode + */ + template <typename IoControlCommand> + boost::system::error_code io_control(IoControlCommand& command, + boost::system::error_code& ec) + { + return this->get_service().io_control( + this->get_implementation(), command, ec); + } + + /// Gets the non-blocking mode of the socket. + /** + * @returns @c true if the socket's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + bool non_blocking() const + { + return this->get_service().non_blocking(this->get_implementation()); + } + + /// Sets the non-blocking mode of the socket. + /** + * @param mode If @c true, the socket's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + void non_blocking(bool mode) + { + boost::system::error_code ec; + this->get_service().non_blocking(this->get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "non_blocking"); + } + + /// Sets the non-blocking mode of the socket. + /** + * @param mode If @c true, the socket's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + boost::system::error_code non_blocking( + bool mode, boost::system::error_code& ec) + { + return this->get_service().non_blocking( + this->get_implementation(), mode, ec); + } + + /// Gets the non-blocking mode of the native socket implementation. + /** + * This function is used to retrieve the non-blocking mode of the underlying + * native socket. This mode has no effect on the behaviour of the socket + * object's synchronous operations. + * + * @returns @c true if the underlying socket is in non-blocking mode and + * direct system calls may fail with boost::asio::error::would_block (or the + * equivalent system error). + * + * @note The current non-blocking mode is cached by the socket object. + * Consequently, the return value may be incorrect if the non-blocking mode + * was set directly on the native socket. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template <typename Handler> + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(boost::system::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = boost::system::error_code(n < 0 ? errno : 0, + * boost::asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == boost::asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == boost::asio::error::would_block + * || ec == boost::asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_write_some(boost::asio::null_buffers(), *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template <typename Handler> + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; + * sock.async_write_some(boost::asio::null_buffers(), op); + * } @endcode + */ + bool native_non_blocking() const + { + return this->get_service().native_non_blocking(this->get_implementation()); + } + + /// Sets the non-blocking mode of the native socket implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native socket. It has no effect on the behaviour of the socket object's + * synchronous operations. + * + * @param mode If @c true, the underlying socket is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @throws boost::system::system_error Thrown on failure. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template <typename Handler> + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(boost::system::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = boost::system::error_code(n < 0 ? errno : 0, + * boost::asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == boost::asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == boost::asio::error::would_block + * || ec == boost::asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_write_some(boost::asio::null_buffers(), *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template <typename Handler> + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; + * sock.async_write_some(boost::asio::null_buffers(), op); + * } @endcode + */ + void native_non_blocking(bool mode) + { + boost::system::error_code ec; + this->get_service().native_non_blocking( + this->get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "native_non_blocking"); + } + + /// Sets the non-blocking mode of the native socket implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native socket. It has no effect on the behaviour of the socket object's + * synchronous operations. + * + * @param mode If @c true, the underlying socket is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @param ec Set to indicate what error occurred, if any. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + * + * @par Example + * This function is intended to allow the encapsulation of arbitrary + * non-blocking system calls as asynchronous operations, in a way that is + * transparent to the user of the socket object. The following example + * illustrates how Linux's @c sendfile system call might be encapsulated: + * @code template <typename Handler> + * struct sendfile_op + * { + * tcp::socket& sock_; + * int fd_; + * Handler handler_; + * off_t offset_; + * std::size_t total_bytes_transferred_; + * + * // Function call operator meeting WriteHandler requirements. + * // Used as the handler for the async_write_some operation. + * void operator()(boost::system::error_code ec, std::size_t) + * { + * // Put the underlying socket into non-blocking mode. + * if (!ec) + * if (!sock_.native_non_blocking()) + * sock_.native_non_blocking(true, ec); + * + * if (!ec) + * { + * for (;;) + * { + * // Try the system call. + * errno = 0; + * int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536); + * ec = boost::system::error_code(n < 0 ? errno : 0, + * boost::asio::error::get_system_category()); + * total_bytes_transferred_ += ec ? 0 : n; + * + * // Retry operation immediately if interrupted by signal. + * if (ec == boost::asio::error::interrupted) + * continue; + * + * // Check if we need to run the operation again. + * if (ec == boost::asio::error::would_block + * || ec == boost::asio::error::try_again) + * { + * // We have to wait for the socket to become ready again. + * sock_.async_write_some(boost::asio::null_buffers(), *this); + * return; + * } + * + * if (ec || n == 0) + * { + * // An error occurred, or we have reached the end of the file. + * // Either way we must exit the loop so we can call the handler. + * break; + * } + * + * // Loop around to try calling sendfile again. + * } + * } + * + * // Pass result back to user's handler. + * handler_(ec, total_bytes_transferred_); + * } + * }; + * + * template <typename Handler> + * void async_sendfile(tcp::socket& sock, int fd, Handler h) + * { + * sendfile_op<Handler> op = { sock, fd, h, 0, 0 }; + * sock.async_write_some(boost::asio::null_buffers(), op); + * } @endcode + */ + boost::system::error_code native_non_blocking( + bool mode, boost::system::error_code& ec) + { + return this->get_service().native_non_blocking( + this->get_implementation(), mode, ec); + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @returns An object that represents the local endpoint of the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); + * @endcode + */ + endpoint_type local_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = this->get_service().local_endpoint( + this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "local_endpoint"); + return ep; + } + + /// Get the local endpoint of the socket. + /** + * This function is used to obtain the locally bound endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the local endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type local_endpoint(boost::system::error_code& ec) const + { + return this->get_service().local_endpoint(this->get_implementation(), ec); + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @returns An object that represents the remote endpoint of the socket. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); + * @endcode + */ + endpoint_type remote_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = this->get_service().remote_endpoint( + this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "remote_endpoint"); + return ep; + } + + /// Get the remote endpoint of the socket. + /** + * This function is used to obtain the remote endpoint of the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the remote endpoint of the socket. + * Returns a default-constructed endpoint object if an error occurred. + * + * @par Example + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type remote_endpoint(boost::system::error_code& ec) const + { + return this->get_service().remote_endpoint(this->get_implementation(), ec); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send); + * @endcode + */ + void shutdown(shutdown_type what) + { + boost::system::error_code ec; + this->get_service().shutdown(this->get_implementation(), what, ec); + boost::asio::detail::throw_error(ec, "shutdown"); + } + + /// Disable sends or receives on the socket. + /** + * This function is used to disable send operations, receive operations, or + * both. + * + * @param what Determines what types of operation will no longer be allowed. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * Shutting down the send side of the socket: + * @code + * boost::asio::ip::tcp::socket socket(io_service); + * ... + * boost::system::error_code ec; + * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code shutdown(shutdown_type what, + boost::system::error_code& ec) + { + return this->get_service().shutdown(this->get_implementation(), what, ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + ~basic_socket() + { + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BASIC_SOCKET_HPP
diff --git a/boost/boost/asio/basic_socket_acceptor.hpp b/boost/boost/asio/basic_socket_acceptor.hpp new file mode 100644 index 0000000..a1a1f8a --- /dev/null +++ b/boost/boost/asio/basic_socket_acceptor.hpp
@@ -0,0 +1,1138 @@ +// +// basic_socket_acceptor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP +#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/basic_socket.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/socket_acceptor_service.hpp> +#include <boost/asio/socket_base.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides the ability to accept new connections. +/** + * The basic_socket_acceptor class template is used for accepting new socket + * connections. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Example + * Opening a socket acceptor with the SO_REUSEADDR option enabled: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port); + * acceptor.open(endpoint.protocol()); + * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(); + * @endcode + */ +template <typename Protocol, + typename SocketAcceptorService = socket_acceptor_service<Protocol> > +class basic_socket_acceptor + : public basic_io_object<SocketAcceptorService>, + public socket_base +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of an + /// acceptor. + typedef typename SocketAcceptorService::native_handle_type native_type; + + /// The native representation of an acceptor. + typedef typename SocketAcceptorService::native_handle_type native_handle_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct an acceptor without opening it. + /** + * This constructor creates an acceptor without opening it to listen for new + * connections. The open() function must be called before the acceptor can + * accept new socket connections. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + */ + explicit basic_socket_acceptor(boost::asio::io_service& io_service) + : basic_io_object<SocketAcceptorService>(io_service) + { + } + + /// Construct an open acceptor. + /** + * This constructor creates an acceptor and automatically opens it. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_acceptor(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_io_object<SocketAcceptorService>(io_service) + { + boost::system::error_code ec; + this->get_service().open(this->get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Construct an acceptor opened on the given endpoint. + /** + * This constructor creates an acceptor and automatically opens it to listen + * for new connections on the specified endpoint. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param endpoint An endpoint on the local machine on which the acceptor + * will listen for new connections. + * + * @param reuse_addr Whether the constructor should set the socket option + * socket_base::reuse_address. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note This constructor is equivalent to the following code: + * @code + * basic_socket_acceptor<Protocol> acceptor(io_service); + * acceptor.open(endpoint.protocol()); + * if (reuse_addr) + * acceptor.set_option(socket_base::reuse_address(true)); + * acceptor.bind(endpoint); + * acceptor.listen(listen_backlog); + * @endcode + */ + basic_socket_acceptor(boost::asio::io_service& io_service, + const endpoint_type& endpoint, bool reuse_addr = true) + : basic_io_object<SocketAcceptorService>(io_service) + { + boost::system::error_code ec; + const protocol_type protocol = endpoint.protocol(); + this->get_service().open(this->get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + if (reuse_addr) + { + this->get_service().set_option(this->get_implementation(), + socket_base::reuse_address(true), ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + this->get_service().bind(this->get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + this->get_service().listen(this->get_implementation(), + socket_base::max_connections, ec); + boost::asio::detail::throw_error(ec, "listen"); + } + + /// Construct a basic_socket_acceptor on an existing native acceptor. + /** + * This constructor creates an acceptor object to hold an existing native + * acceptor. + * + * @param io_service The io_service object that the acceptor will use to + * dispatch handlers for any asynchronous operations performed on the + * acceptor. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_socket_acceptor(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_handle_type& native_acceptor) + : basic_io_object<SocketAcceptorService>(io_service) + { + boost::system::error_code ec; + this->get_service().assign(this->get_implementation(), + protocol, native_acceptor, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_socket_acceptor from another. + /** + * This constructor moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket_acceptor(io_service&) constructor. + */ + basic_socket_acceptor(basic_socket_acceptor&& other) + : basic_io_object<SocketAcceptorService>( + BOOST_ASIO_MOVE_CAST(basic_socket_acceptor)(other)) + { + } + + /// Move-assign a basic_socket_acceptor from another. + /** + * This assignment operator moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket_acceptor(io_service&) constructor. + */ + basic_socket_acceptor& operator=(basic_socket_acceptor&& other) + { + basic_io_object<SocketAcceptorService>::operator=( + BOOST_ASIO_MOVE_CAST(basic_socket_acceptor)(other)); + return *this; + } + + // All socket acceptors have access to each other's implementations. + template <typename Protocol1, typename SocketAcceptorService1> + friend class basic_socket_acceptor; + + /// Move-construct a basic_socket_acceptor from an acceptor of another + /// protocol type. + /** + * This constructor moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SocketAcceptorService1> + basic_socket_acceptor( + basic_socket_acceptor<Protocol1, SocketAcceptorService1>&& other, + typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) + : basic_io_object<SocketAcceptorService>(other.get_io_service()) + { + this->get_service().template converting_move_construct<Protocol1>( + this->get_implementation(), other.get_implementation()); + } + + /// Move-assign a basic_socket_acceptor from an acceptor of another protocol + /// type. + /** + * This assignment operator moves an acceptor from one object to another. + * + * @param other The other basic_socket_acceptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_socket(io_service&) constructor. + */ + template <typename Protocol1, typename SocketAcceptorService1> + typename enable_if<is_convertible<Protocol1, Protocol>::value, + basic_socket_acceptor>::type& operator=( + basic_socket_acceptor<Protocol1, SocketAcceptorService1>&& other) + { + basic_socket_acceptor tmp(BOOST_ASIO_MOVE_CAST2(basic_socket_acceptor< + Protocol1, SocketAcceptorService1>)(other)); + basic_io_object<SocketAcceptorService>::operator=( + BOOST_ASIO_MOVE_CAST(basic_socket_acceptor)(tmp)); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Open the acceptor using the specified protocol. + /** + * This function opens the socket acceptor so that it will use the specified + * protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * acceptor.open(boost::asio::ip::tcp::v4()); + * @endcode + */ + void open(const protocol_type& protocol = protocol_type()) + { + boost::system::error_code ec; + this->get_service().open(this->get_implementation(), protocol, ec); + boost::asio::detail::throw_error(ec, "open"); + } + + /// Open the acceptor using the specified protocol. + /** + * This function opens the socket acceptor so that it will use the specified + * protocol. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * boost::system::error_code ec; + * acceptor.open(boost::asio::ip::tcp::v4(), ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code open(const protocol_type& protocol, + boost::system::error_code& ec) + { + return this->get_service().open(this->get_implementation(), protocol, ec); + } + + /// Assigns an existing native acceptor to the acceptor. + /* + * This function opens the acceptor to hold an existing native acceptor. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_acceptor A native acceptor. + * + * @throws boost::system::system_error Thrown on failure. + */ + void assign(const protocol_type& protocol, + const native_handle_type& native_acceptor) + { + boost::system::error_code ec; + this->get_service().assign(this->get_implementation(), + protocol, native_acceptor, ec); + boost::asio::detail::throw_error(ec, "assign"); + } + + /// Assigns an existing native acceptor to the acceptor. + /* + * This function opens the acceptor to hold an existing native acceptor. + * + * @param protocol An object specifying which protocol is to be used. + * + * @param native_acceptor A native acceptor. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code assign(const protocol_type& protocol, + const native_handle_type& native_acceptor, boost::system::error_code& ec) + { + return this->get_service().assign(this->get_implementation(), + protocol, native_acceptor, ec); + } + + /// Determine whether the acceptor is open. + bool is_open() const + { + return this->get_service().is_open(this->get_implementation()); + } + + /// Bind the acceptor to the given local endpoint. + /** + * This function binds the socket acceptor to the specified endpoint on the + * local machine. + * + * @param endpoint An endpoint on the local machine to which the socket + * acceptor will be bound. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); + * acceptor.open(endpoint.protocol()); + * acceptor.bind(endpoint); + * @endcode + */ + void bind(const endpoint_type& endpoint) + { + boost::system::error_code ec; + this->get_service().bind(this->get_implementation(), endpoint, ec); + boost::asio::detail::throw_error(ec, "bind"); + } + + /// Bind the acceptor to the given local endpoint. + /** + * This function binds the socket acceptor to the specified endpoint on the + * local machine. + * + * @param endpoint An endpoint on the local machine to which the socket + * acceptor will be bound. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345); + * acceptor.open(endpoint.protocol()); + * boost::system::error_code ec; + * acceptor.bind(endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code bind(const endpoint_type& endpoint, + boost::system::error_code& ec) + { + return this->get_service().bind(this->get_implementation(), endpoint, ec); + } + + /// Place the acceptor into the state where it will listen for new + /// connections. + /** + * This function puts the socket acceptor into the state where it may accept + * new connections. + * + * @param backlog The maximum length of the queue of pending connections. + * + * @throws boost::system::system_error Thrown on failure. + */ + void listen(int backlog = socket_base::max_connections) + { + boost::system::error_code ec; + this->get_service().listen(this->get_implementation(), backlog, ec); + boost::asio::detail::throw_error(ec, "listen"); + } + + /// Place the acceptor into the state where it will listen for new + /// connections. + /** + * This function puts the socket acceptor into the state where it may accept + * new connections. + * + * @param backlog The maximum length of the queue of pending connections. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::system::error_code ec; + * acceptor.listen(boost::asio::socket_base::max_connections, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code listen(int backlog, boost::system::error_code& ec) + { + return this->get_service().listen(this->get_implementation(), backlog, ec); + } + + /// Close the acceptor. + /** + * This function is used to close the acceptor. Any asynchronous accept + * operations will be cancelled immediately. + * + * A subsequent call to open() is required before the acceptor can again be + * used to again perform socket accept operations. + * + * @throws boost::system::system_error Thrown on failure. + */ + void close() + { + boost::system::error_code ec; + this->get_service().close(this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "close"); + } + + /// Close the acceptor. + /** + * This function is used to close the acceptor. Any asynchronous accept + * operations will be cancelled immediately. + * + * A subsequent call to open() is required before the acceptor can again be + * used to again perform socket accept operations. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::system::error_code ec; + * acceptor.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + boost::system::error_code close(boost::system::error_code& ec) + { + return this->get_service().close(this->get_implementation(), ec); + } + + /// (Deprecated: Use native_handle().) Get the native acceptor representation. + /** + * This function may be used to obtain the underlying representation of the + * acceptor. This is intended to allow access to native acceptor functionality + * that is not otherwise provided. + */ + native_type native() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Get the native acceptor representation. + /** + * This function may be used to obtain the underlying representation of the + * acceptor. This is intended to allow access to native acceptor functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return this->get_service().native_handle(this->get_implementation()); + } + + /// Cancel all asynchronous operations associated with the acceptor. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @throws boost::system::system_error Thrown on failure. + */ + void cancel() + { + boost::system::error_code ec; + this->get_service().cancel(this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the acceptor. + /** + * This function causes all outstanding asynchronous connect, send and receive + * operations to finish immediately, and the handlers for cancelled operations + * will be passed the boost::asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + boost::system::error_code cancel(boost::system::error_code& ec) + { + return this->get_service().cancel(this->get_implementation(), ec); + } + + /// Set an option on the acceptor. + /** + * This function is used to set an option on the acceptor. + * + * @param option The new option value to be set on the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::reuse_address + * boost::asio::socket_base::enable_connection_aborted + * + * @par Example + * Setting the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option(true); + * acceptor.set_option(option); + * @endcode + */ + template <typename SettableSocketOption> + void set_option(const SettableSocketOption& option) + { + boost::system::error_code ec; + this->get_service().set_option(this->get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "set_option"); + } + + /// Set an option on the acceptor. + /** + * This function is used to set an option on the acceptor. + * + * @param option The new option value to be set on the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa SettableSocketOption @n + * boost::asio::socket_base::reuse_address + * boost::asio::socket_base::enable_connection_aborted + * + * @par Example + * Setting the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option(true); + * boost::system::error_code ec; + * acceptor.set_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename SettableSocketOption> + boost::system::error_code set_option(const SettableSocketOption& option, + boost::system::error_code& ec) + { + return this->get_service().set_option( + this->get_implementation(), option, ec); + } + + /// Get an option from the acceptor. + /** + * This function is used to get the current value of an option on the + * acceptor. + * + * @param option The option value to be obtained from the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::reuse_address + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option; + * acceptor.get_option(option); + * bool is_set = option.get(); + * @endcode + */ + template <typename GettableSocketOption> + void get_option(GettableSocketOption& option) + { + boost::system::error_code ec; + this->get_service().get_option(this->get_implementation(), option, ec); + boost::asio::detail::throw_error(ec, "get_option"); + } + + /// Get an option from the acceptor. + /** + * This function is used to get the current value of an option on the + * acceptor. + * + * @param option The option value to be obtained from the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa GettableSocketOption @n + * boost::asio::socket_base::reuse_address + * + * @par Example + * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::reuse_address option; + * boost::system::error_code ec; + * acceptor.get_option(option, ec); + * if (ec) + * { + * // An error occurred. + * } + * bool is_set = option.get(); + * @endcode + */ + template <typename GettableSocketOption> + boost::system::error_code get_option(GettableSocketOption& option, + boost::system::error_code& ec) + { + return this->get_service().get_option( + this->get_implementation(), option, ec); + } + + /// Perform an IO control command on the acceptor. + /** + * This function is used to execute an IO control command on the acceptor. + * + * @param command The IO control command to be performed on the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); + * socket.io_control(command); + * @endcode + */ + template <typename IoControlCommand> + void io_control(IoControlCommand& command) + { + boost::system::error_code ec; + this->get_service().io_control(this->get_implementation(), command, ec); + boost::asio::detail::throw_error(ec, "io_control"); + } + + /// Perform an IO control command on the acceptor. + /** + * This function is used to execute an IO control command on the acceptor. + * + * @param command The IO control command to be performed on the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @sa IoControlCommand @n + * boost::asio::socket_base::non_blocking_io + * + * @par Example + * Getting the number of bytes ready to read: + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::acceptor::non_blocking_io command(true); + * boost::system::error_code ec; + * socket.io_control(command, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename IoControlCommand> + boost::system::error_code io_control(IoControlCommand& command, + boost::system::error_code& ec) + { + return this->get_service().io_control( + this->get_implementation(), command, ec); + } + + /// Gets the non-blocking mode of the acceptor. + /** + * @returns @c true if the acceptor's synchronous operations will fail with + * boost::asio::error::would_block if they are unable to perform the requested + * operation immediately. If @c false, synchronous operations will block + * until complete. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + bool non_blocking() const + { + return this->get_service().non_blocking(this->get_implementation()); + } + + /// Sets the non-blocking mode of the acceptor. + /** + * @param mode If @c true, the acceptor's synchronous operations will fail + * with boost::asio::error::would_block if they are unable to perform the + * requested operation immediately. If @c false, synchronous operations will + * block until complete. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + void non_blocking(bool mode) + { + boost::system::error_code ec; + this->get_service().non_blocking(this->get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "non_blocking"); + } + + /// Sets the non-blocking mode of the acceptor. + /** + * @param mode If @c true, the acceptor's synchronous operations will fail + * with boost::asio::error::would_block if they are unable to perform the + * requested operation immediately. If @c false, synchronous operations will + * block until complete. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note The non-blocking mode has no effect on the behaviour of asynchronous + * operations. Asynchronous operations will never fail with the error + * boost::asio::error::would_block. + */ + boost::system::error_code non_blocking( + bool mode, boost::system::error_code& ec) + { + return this->get_service().non_blocking( + this->get_implementation(), mode, ec); + } + + /// Gets the non-blocking mode of the native acceptor implementation. + /** + * This function is used to retrieve the non-blocking mode of the underlying + * native acceptor. This mode has no effect on the behaviour of the acceptor + * object's synchronous operations. + * + * @returns @c true if the underlying acceptor is in non-blocking mode and + * direct system calls may fail with boost::asio::error::would_block (or the + * equivalent system error). + * + * @note The current non-blocking mode is cached by the acceptor object. + * Consequently, the return value may be incorrect if the non-blocking mode + * was set directly on the native acceptor. + */ + bool native_non_blocking() const + { + return this->get_service().native_non_blocking(this->get_implementation()); + } + + /// Sets the non-blocking mode of the native acceptor implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native acceptor. It has no effect on the behaviour of the acceptor object's + * synchronous operations. + * + * @param mode If @c true, the underlying acceptor is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @throws boost::system::system_error Thrown on failure. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + */ + void native_non_blocking(bool mode) + { + boost::system::error_code ec; + this->get_service().native_non_blocking( + this->get_implementation(), mode, ec); + boost::asio::detail::throw_error(ec, "native_non_blocking"); + } + + /// Sets the non-blocking mode of the native acceptor implementation. + /** + * This function is used to modify the non-blocking mode of the underlying + * native acceptor. It has no effect on the behaviour of the acceptor object's + * synchronous operations. + * + * @param mode If @c true, the underlying acceptor is put into non-blocking + * mode and direct system calls may fail with boost::asio::error::would_block + * (or the equivalent system error). + * + * @param ec Set to indicate what error occurred, if any. If the @c mode is + * @c false, but the current value of @c non_blocking() is @c true, this + * function fails with boost::asio::error::invalid_argument, as the + * combination does not make sense. + */ + boost::system::error_code native_non_blocking( + bool mode, boost::system::error_code& ec) + { + return this->get_service().native_non_blocking( + this->get_implementation(), mode, ec); + } + + /// Get the local endpoint of the acceptor. + /** + * This function is used to obtain the locally bound endpoint of the acceptor. + * + * @returns An object that represents the local endpoint of the acceptor. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); + * @endcode + */ + endpoint_type local_endpoint() const + { + boost::system::error_code ec; + endpoint_type ep = this->get_service().local_endpoint( + this->get_implementation(), ec); + boost::asio::detail::throw_error(ec, "local_endpoint"); + return ep; + } + + /// Get the local endpoint of the acceptor. + /** + * This function is used to obtain the locally bound endpoint of the acceptor. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns An object that represents the local endpoint of the acceptor. + * Returns a default-constructed endpoint object if an error occurred and the + * error handler did not throw an exception. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::system::error_code ec; + * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + endpoint_type local_endpoint(boost::system::error_code& ec) const + { + return this->get_service().local_endpoint(this->get_implementation(), ec); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer into the + * given socket. The function call will block until a new connection has been + * accepted successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::socket socket(io_service); + * acceptor.accept(socket); + * @endcode + */ + template <typename Protocol1, typename SocketService> + void accept(basic_socket<Protocol1, SocketService>& peer, + typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) + { + boost::system::error_code ec; + this->get_service().accept(this->get_implementation(), + peer, static_cast<endpoint_type*>(0), ec); + boost::asio::detail::throw_error(ec, "accept"); + } + + /// Accept a new connection. + /** + * This function is used to accept a new connection from a peer into the + * given socket. The function call will block until a new connection has been + * accepted successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::soocket socket(io_service); + * boost::system::error_code ec; + * acceptor.accept(socket, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename Protocol1, typename SocketService> + boost::system::error_code accept( + basic_socket<Protocol1, SocketService>& peer, + boost::system::error_code& ec, + typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) + { + return this->get_service().accept(this->get_implementation(), + peer, static_cast<endpoint_type*>(0), ec); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection into a + * socket. The function call always returns immediately. + * + * @param peer The socket into which the new connection will be accepted. + * Ownership of the peer object is retained by the caller, which must + * guarantee that it is valid until the handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * @code + * void accept_handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Accept succeeded. + * } + * } + * + * ... + * + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::socket socket(io_service); + * acceptor.async_accept(socket, accept_handler); + * @endcode + */ + template <typename Protocol1, typename SocketService, typename AcceptHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, + void (boost::system::error_code)) + async_accept(basic_socket<Protocol1, SocketService>& peer, + BOOST_ASIO_MOVE_ARG(AcceptHandler) handler, + typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a AcceptHandler. + BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; + + return this->get_service().async_accept(this->get_implementation(), + peer, static_cast<endpoint_type*>(0), + BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)); + } + + /// Accept a new connection and obtain the endpoint of the peer + /** + * This function is used to accept a new connection from a peer into the + * given socket, and additionally provide the endpoint of the remote peer. + * The function call will block until a new connection has been accepted + * successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param peer_endpoint An endpoint object which will receive the endpoint of + * the remote peer. + * + * @throws boost::system::system_error Thrown on failure. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint; + * acceptor.accept(socket, endpoint); + * @endcode + */ + template <typename SocketService> + void accept(basic_socket<protocol_type, SocketService>& peer, + endpoint_type& peer_endpoint) + { + boost::system::error_code ec; + this->get_service().accept(this->get_implementation(), + peer, &peer_endpoint, ec); + boost::asio::detail::throw_error(ec, "accept"); + } + + /// Accept a new connection and obtain the endpoint of the peer + /** + * This function is used to accept a new connection from a peer into the + * given socket, and additionally provide the endpoint of the remote peer. + * The function call will block until a new connection has been accepted + * successfully or an error occurs. + * + * @param peer The socket into which the new connection will be accepted. + * + * @param peer_endpoint An endpoint object which will receive the endpoint of + * the remote peer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * boost::asio::ip::tcp::acceptor acceptor(io_service); + * ... + * boost::asio::ip::tcp::socket socket(io_service); + * boost::asio::ip::tcp::endpoint endpoint; + * boost::system::error_code ec; + * acceptor.accept(socket, endpoint, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + template <typename SocketService> + boost::system::error_code accept( + basic_socket<protocol_type, SocketService>& peer, + endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + return this->get_service().accept( + this->get_implementation(), peer, &peer_endpoint, ec); + } + + /// Start an asynchronous accept. + /** + * This function is used to asynchronously accept a new connection into a + * socket, and additionally obtain the endpoint of the remote peer. The + * function call always returns immediately. + * + * @param peer The socket into which the new connection will be accepted. + * Ownership of the peer object is retained by the caller, which must + * guarantee that it is valid until the handler is called. + * + * @param peer_endpoint An endpoint object into which the endpoint of the + * remote peer will be written. Ownership of the peer_endpoint object is + * retained by the caller, which must guarantee that it is valid until the + * handler is called. + * + * @param handler The handler to be called when the accept operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template <typename SocketService, typename AcceptHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, + void (boost::system::error_code)) + async_accept(basic_socket<protocol_type, SocketService>& peer, + endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a AcceptHandler. + BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check; + + return this->get_service().async_accept(this->get_implementation(), peer, + &peer_endpoint, BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler)); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP
diff --git a/boost/boost/asio/basic_socket_iostream.hpp b/boost/boost/asio/basic_socket_iostream.hpp new file mode 100644 index 0000000..a0031cb --- /dev/null +++ b/boost/boost/asio/basic_socket_iostream.hpp
@@ -0,0 +1,288 @@ +// +// basic_socket_iostream.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP +#define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_NO_IOSTREAM) + +#include <istream> +#include <ostream> +#include <boost/asio/basic_socket_streambuf.hpp> +#include <boost/asio/stream_socket_service.hpp> + +#if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +# include <boost/asio/detail/variadic_templates.hpp> + +// A macro that should expand to: +// template <typename T1, ..., typename Tn> +// explicit basic_socket_iostream(T1 x1, ..., Tn xn) +// : std::basic_iostream<char>( +// &this->detail::socket_iostream_base< +// Protocol, StreamSocketService, Time, +// TimeTraits, TimerService>::streambuf_) +// { +// if (rdbuf()->connect(x1, ..., xn) == 0) +// this->setstate(std::ios_base::failbit); +// } +// This macro should only persist within this file. + +# define BOOST_ASIO_PRIVATE_CTR_DEF(n) \ + template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + explicit basic_socket_iostream(BOOST_ASIO_VARIADIC_PARAMS(n)) \ + : std::basic_iostream<char>( \ + &this->detail::socket_iostream_base< \ + Protocol, StreamSocketService, Time, \ + TimeTraits, TimerService>::streambuf_) \ + { \ + this->setf(std::ios_base::unitbuf); \ + if (rdbuf()->connect(BOOST_ASIO_VARIADIC_ARGS(n)) == 0) \ + this->setstate(std::ios_base::failbit); \ + } \ + /**/ + +// A macro that should expand to: +// template <typename T1, ..., typename Tn> +// void connect(T1 x1, ..., Tn xn) +// { +// if (rdbuf()->connect(x1, ..., xn) == 0) +// this->setstate(std::ios_base::failbit); +// } +// This macro should only persist within this file. + +# define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \ + template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + void connect(BOOST_ASIO_VARIADIC_PARAMS(n)) \ + { \ + if (rdbuf()->connect(BOOST_ASIO_VARIADIC_ARGS(n)) == 0) \ + this->setstate(std::ios_base::failbit); \ + } \ + /**/ + +#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// A separate base class is used to ensure that the streambuf is initialised +// prior to the basic_socket_iostream's basic_iostream base class. +template <typename Protocol, typename StreamSocketService, + typename Time, typename TimeTraits, typename TimerService> +class socket_iostream_base +{ +protected: + basic_socket_streambuf<Protocol, StreamSocketService, + Time, TimeTraits, TimerService> streambuf_; +}; + +} + +/// Iostream interface for a socket. +template <typename Protocol, + typename StreamSocketService = stream_socket_service<Protocol>, +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ + || defined(GENERATING_DOCUMENTATION) + typename Time = boost::posix_time::ptime, + typename TimeTraits = boost::asio::time_traits<Time>, + typename TimerService = deadline_timer_service<Time, TimeTraits> > +#else + typename Time = steady_timer::clock_type, + typename TimeTraits = steady_timer::traits_type, + typename TimerService = steady_timer::service_type> +#endif +class basic_socket_iostream + : private detail::socket_iostream_base<Protocol, + StreamSocketService, Time, TimeTraits, TimerService>, + public std::basic_iostream<char> +{ +private: + // These typedefs are intended keep this class's implementation independent + // of whether it's using Boost.DateTime, Boost.Chrono or std::chrono. +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) + typedef TimeTraits traits_helper; +#else + typedef detail::chrono_time_traits<Time, TimeTraits> traits_helper; +#endif + +public: + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The time type. + typedef typename TimeTraits::time_type time_type; + + /// The duration type. + typedef typename TimeTraits::duration_type duration_type; +#else + typedef typename traits_helper::time_type time_type; + typedef typename traits_helper::duration_type duration_type; +#endif + + /// Construct a basic_socket_iostream without establishing a connection. + basic_socket_iostream() + : std::basic_iostream<char>( + &this->detail::socket_iostream_base< + Protocol, StreamSocketService, Time, + TimeTraits, TimerService>::streambuf_) + { + this->setf(std::ios_base::unitbuf); + } + +#if defined(GENERATING_DOCUMENTATION) + /// Establish a connection to an endpoint corresponding to a resolver query. + /** + * This constructor automatically establishes a connection based on the + * supplied resolver query parameters. The arguments are used to construct + * a resolver query object. + */ + template <typename T1, ..., typename TN> + explicit basic_socket_iostream(T1 t1, ..., TN tn); +#elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + template <typename... T> + explicit basic_socket_iostream(T... x) + : std::basic_iostream<char>( + &this->detail::socket_iostream_base< + Protocol, StreamSocketService, Time, + TimeTraits, TimerService>::streambuf_) + { + this->setf(std::ios_base::unitbuf); + if (rdbuf()->connect(x...) == 0) + this->setstate(std::ios_base::failbit); + } +#else + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CTR_DEF) +#endif + +#if defined(GENERATING_DOCUMENTATION) + /// Establish a connection to an endpoint corresponding to a resolver query. + /** + * This function automatically establishes a connection based on the supplied + * resolver query parameters. The arguments are used to construct a resolver + * query object. + */ + template <typename T1, ..., typename TN> + void connect(T1 t1, ..., TN tn); +#elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + template <typename... T> + void connect(T... x) + { + if (rdbuf()->connect(x...) == 0) + this->setstate(std::ios_base::failbit); + } +#else + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CONNECT_DEF) +#endif + + /// Close the connection. + void close() + { + if (rdbuf()->close() == 0) + this->setstate(std::ios_base::failbit); + } + + /// Return a pointer to the underlying streambuf. + basic_socket_streambuf<Protocol, StreamSocketService, + Time, TimeTraits, TimerService>* rdbuf() const + { + return const_cast<basic_socket_streambuf<Protocol, StreamSocketService, + Time, TimeTraits, TimerService>*>( + &this->detail::socket_iostream_base< + Protocol, StreamSocketService, Time, + TimeTraits, TimerService>::streambuf_); + } + + /// Get the last error associated with the stream. + /** + * @return An \c error_code corresponding to the last error from the stream. + * + * @par Example + * To print the error associated with a failure to establish a connection: + * @code tcp::iostream s("www.boost.org", "http"); + * if (!s) + * { + * std::cout << "Error: " << s.error().message() << std::endl; + * } @endcode + */ + const boost::system::error_code& error() const + { + return rdbuf()->puberror(); + } + + /// Get the stream's expiry time as an absolute time. + /** + * @return An absolute time value representing the stream's expiry time. + */ + time_type expires_at() const + { + return rdbuf()->expires_at(); + } + + /// Set the stream's expiry time as an absolute time. + /** + * This function sets the expiry time associated with the stream. Stream + * operations performed after this time (where the operations cannot be + * completed using the internal buffers) will fail with the error + * boost::asio::error::operation_aborted. + * + * @param expiry_time The expiry time to be used for the stream. + */ + void expires_at(const time_type& expiry_time) + { + rdbuf()->expires_at(expiry_time); + } + + /// Get the timer's expiry time relative to now. + /** + * @return A relative time value representing the stream's expiry time. + */ + duration_type expires_from_now() const + { + return rdbuf()->expires_from_now(); + } + + /// Set the stream's expiry time relative to now. + /** + * This function sets the expiry time associated with the stream. Stream + * operations performed after this time (where the operations cannot be + * completed using the internal buffers) will fail with the error + * boost::asio::error::operation_aborted. + * + * @param expiry_time The expiry time to be used for the timer. + */ + void expires_from_now(const duration_type& expiry_time) + { + rdbuf()->expires_from_now(expiry_time); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) +# undef BOOST_ASIO_PRIVATE_CTR_DEF +# undef BOOST_ASIO_PRIVATE_CONNECT_DEF +#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +#endif // !defined(BOOST_ASIO_NO_IOSTREAM) + +#endif // BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP
diff --git a/boost/boost/asio/basic_socket_streambuf.hpp b/boost/boost/asio/basic_socket_streambuf.hpp new file mode 100644 index 0000000..5595e99 --- /dev/null +++ b/boost/boost/asio/basic_socket_streambuf.hpp
@@ -0,0 +1,569 @@ +// +// basic_socket_streambuf.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP +#define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_NO_IOSTREAM) + +#include <streambuf> +#include <boost/asio/basic_socket.hpp> +#include <boost/asio/deadline_timer_service.hpp> +#include <boost/asio/detail/array.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/stream_socket_service.hpp> + +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) +# include <boost/asio/deadline_timer.hpp> +#else +# include <boost/asio/steady_timer.hpp> +#endif + +#if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +# include <boost/asio/detail/variadic_templates.hpp> + +// A macro that should expand to: +// template <typename T1, ..., typename Tn> +// basic_socket_streambuf<Protocol, StreamSocketService, +// Time, TimeTraits, TimerService>* connect( +// T1 x1, ..., Tn xn) +// { +// init_buffers(); +// this->basic_socket<Protocol, StreamSocketService>::close(ec_); +// typedef typename Protocol::resolver resolver_type; +// typedef typename resolver_type::query resolver_query; +// resolver_query query(x1, ..., xn); +// resolve_and_connect(query); +// return !ec_ ? this : 0; +// } +// This macro should only persist within this file. + +# define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \ + template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \ + basic_socket_streambuf<Protocol, StreamSocketService, \ + Time, TimeTraits, TimerService>* connect(BOOST_ASIO_VARIADIC_PARAMS(n)) \ + { \ + init_buffers(); \ + this->basic_socket<Protocol, StreamSocketService>::close(ec_); \ + typedef typename Protocol::resolver resolver_type; \ + typedef typename resolver_type::query resolver_query; \ + resolver_query query(BOOST_ASIO_VARIADIC_ARGS(n)); \ + resolve_and_connect(query); \ + return !ec_ ? this : 0; \ + } \ + /**/ + +#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// A separate base class is used to ensure that the io_service is initialised +// prior to the basic_socket_streambuf's basic_socket base class. +class socket_streambuf_base +{ +protected: + io_service io_service_; +}; + +} // namespace detail + +/// Iostream streambuf for a socket. +template <typename Protocol, + typename StreamSocketService = stream_socket_service<Protocol>, +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ + || defined(GENERATING_DOCUMENTATION) + typename Time = boost::posix_time::ptime, + typename TimeTraits = boost::asio::time_traits<Time>, + typename TimerService = deadline_timer_service<Time, TimeTraits> > +#else + typename Time = steady_timer::clock_type, + typename TimeTraits = steady_timer::traits_type, + typename TimerService = steady_timer::service_type> +#endif +class basic_socket_streambuf + : public std::streambuf, + private detail::socket_streambuf_base, + public basic_socket<Protocol, StreamSocketService> +{ +private: + // These typedefs are intended keep this class's implementation independent + // of whether it's using Boost.DateTime, Boost.Chrono or std::chrono. +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) + typedef TimeTraits traits_helper; +#else + typedef detail::chrono_time_traits<Time, TimeTraits> traits_helper; +#endif + +public: + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The time type. + typedef typename TimeTraits::time_type time_type; + + /// The duration type. + typedef typename TimeTraits::duration_type duration_type; +#else + typedef typename traits_helper::time_type time_type; + typedef typename traits_helper::duration_type duration_type; +#endif + + /// Construct a basic_socket_streambuf without establishing a connection. + basic_socket_streambuf() + : basic_socket<Protocol, StreamSocketService>( + this->detail::socket_streambuf_base::io_service_), + unbuffered_(false), + timer_service_(0), + timer_state_(no_timer) + { + init_buffers(); + } + + /// Destructor flushes buffered data. + virtual ~basic_socket_streambuf() + { + if (pptr() != pbase()) + overflow(traits_type::eof()); + + destroy_timer(); + } + + /// Establish a connection. + /** + * This function establishes a connection to the specified endpoint. + * + * @return \c this if a connection was successfully established, a null + * pointer otherwise. + */ + basic_socket_streambuf<Protocol, StreamSocketService, + Time, TimeTraits, TimerService>* connect( + const endpoint_type& endpoint) + { + init_buffers(); + + this->basic_socket<Protocol, StreamSocketService>::close(ec_); + + if (timer_state_ == timer_has_expired) + { + ec_ = boost::asio::error::operation_aborted; + return 0; + } + + io_handler handler = { this }; + this->basic_socket<Protocol, StreamSocketService>::async_connect( + endpoint, handler); + + ec_ = boost::asio::error::would_block; + this->get_service().get_io_service().reset(); + do this->get_service().get_io_service().run_one(); + while (ec_ == boost::asio::error::would_block); + + return !ec_ ? this : 0; + } + +#if defined(GENERATING_DOCUMENTATION) + /// Establish a connection. + /** + * This function automatically establishes a connection based on the supplied + * resolver query parameters. The arguments are used to construct a resolver + * query object. + * + * @return \c this if a connection was successfully established, a null + * pointer otherwise. + */ + template <typename T1, ..., typename TN> + basic_socket_streambuf<Protocol, StreamSocketService>* connect( + T1 t1, ..., TN tn); +#elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + template <typename... T> + basic_socket_streambuf<Protocol, StreamSocketService, + Time, TimeTraits, TimerService>* connect(T... x) + { + init_buffers(); + this->basic_socket<Protocol, StreamSocketService>::close(ec_); + typedef typename Protocol::resolver resolver_type; + typedef typename resolver_type::query resolver_query; + resolver_query query(x...); + resolve_and_connect(query); + return !ec_ ? this : 0; + } +#else + BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CONNECT_DEF) +#endif + + /// Close the connection. + /** + * @return \c this if a connection was successfully established, a null + * pointer otherwise. + */ + basic_socket_streambuf<Protocol, StreamSocketService, + Time, TimeTraits, TimerService>* close() + { + sync(); + this->basic_socket<Protocol, StreamSocketService>::close(ec_); + if (!ec_) + init_buffers(); + return !ec_ ? this : 0; + } + + /// Get the last error associated with the stream buffer. + /** + * @return An \c error_code corresponding to the last error from the stream + * buffer. + */ + const boost::system::error_code& puberror() const + { + return error(); + } + + /// Get the stream buffer's expiry time as an absolute time. + /** + * @return An absolute time value representing the stream buffer's expiry + * time. + */ + time_type expires_at() const + { + return timer_service_ + ? timer_service_->expires_at(timer_implementation_) + : time_type(); + } + + /// Set the stream buffer's expiry time as an absolute time. + /** + * This function sets the expiry time associated with the stream. Stream + * operations performed after this time (where the operations cannot be + * completed using the internal buffers) will fail with the error + * boost::asio::error::operation_aborted. + * + * @param expiry_time The expiry time to be used for the stream. + */ + void expires_at(const time_type& expiry_time) + { + construct_timer(); + + boost::system::error_code ec; + timer_service_->expires_at(timer_implementation_, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_at"); + + start_timer(); + } + + /// Get the stream buffer's expiry time relative to now. + /** + * @return A relative time value representing the stream buffer's expiry time. + */ + duration_type expires_from_now() const + { + return traits_helper::subtract(expires_at(), traits_helper::now()); + } + + /// Set the stream buffer's expiry time relative to now. + /** + * This function sets the expiry time associated with the stream. Stream + * operations performed after this time (where the operations cannot be + * completed using the internal buffers) will fail with the error + * boost::asio::error::operation_aborted. + * + * @param expiry_time The expiry time to be used for the timer. + */ + void expires_from_now(const duration_type& expiry_time) + { + construct_timer(); + + boost::system::error_code ec; + timer_service_->expires_from_now(timer_implementation_, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_from_now"); + + start_timer(); + } + +protected: + int_type underflow() + { + if (gptr() == egptr()) + { + if (timer_state_ == timer_has_expired) + { + ec_ = boost::asio::error::operation_aborted; + return traits_type::eof(); + } + + io_handler handler = { this }; + this->get_service().async_receive(this->get_implementation(), + boost::asio::buffer(boost::asio::buffer(get_buffer_) + putback_max), + 0, handler); + + ec_ = boost::asio::error::would_block; + this->get_service().get_io_service().reset(); + do this->get_service().get_io_service().run_one(); + while (ec_ == boost::asio::error::would_block); + if (ec_) + return traits_type::eof(); + + setg(&get_buffer_[0], &get_buffer_[0] + putback_max, + &get_buffer_[0] + putback_max + bytes_transferred_); + return traits_type::to_int_type(*gptr()); + } + else + { + return traits_type::eof(); + } + } + + int_type overflow(int_type c) + { + if (unbuffered_) + { + if (traits_type::eq_int_type(c, traits_type::eof())) + { + // Nothing to do. + return traits_type::not_eof(c); + } + else + { + if (timer_state_ == timer_has_expired) + { + ec_ = boost::asio::error::operation_aborted; + return traits_type::eof(); + } + + // Send the single character immediately. + char_type ch = traits_type::to_char_type(c); + io_handler handler = { this }; + this->get_service().async_send(this->get_implementation(), + boost::asio::buffer(&ch, sizeof(char_type)), 0, handler); + + ec_ = boost::asio::error::would_block; + this->get_service().get_io_service().reset(); + do this->get_service().get_io_service().run_one(); + while (ec_ == boost::asio::error::would_block); + if (ec_) + return traits_type::eof(); + + return c; + } + } + else + { + // Send all data in the output buffer. + boost::asio::const_buffer buffer = + boost::asio::buffer(pbase(), pptr() - pbase()); + while (boost::asio::buffer_size(buffer) > 0) + { + if (timer_state_ == timer_has_expired) + { + ec_ = boost::asio::error::operation_aborted; + return traits_type::eof(); + } + + io_handler handler = { this }; + this->get_service().async_send(this->get_implementation(), + boost::asio::buffer(buffer), 0, handler); + + ec_ = boost::asio::error::would_block; + this->get_service().get_io_service().reset(); + do this->get_service().get_io_service().run_one(); + while (ec_ == boost::asio::error::would_block); + if (ec_) + return traits_type::eof(); + + buffer = buffer + bytes_transferred_; + } + setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size()); + + // If the new character is eof then our work here is done. + if (traits_type::eq_int_type(c, traits_type::eof())) + return traits_type::not_eof(c); + + // Add the new character to the output buffer. + *pptr() = traits_type::to_char_type(c); + pbump(1); + return c; + } + } + + int sync() + { + return overflow(traits_type::eof()); + } + + std::streambuf* setbuf(char_type* s, std::streamsize n) + { + if (pptr() == pbase() && s == 0 && n == 0) + { + unbuffered_ = true; + setp(0, 0); + return this; + } + + return 0; + } + + /// Get the last error associated with the stream buffer. + /** + * @return An \c error_code corresponding to the last error from the stream + * buffer. + */ + virtual const boost::system::error_code& error() const + { + return ec_; + } + +private: + void init_buffers() + { + setg(&get_buffer_[0], + &get_buffer_[0] + putback_max, + &get_buffer_[0] + putback_max); + if (unbuffered_) + setp(0, 0); + else + setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size()); + } + + template <typename ResolverQuery> + void resolve_and_connect(const ResolverQuery& query) + { + typedef typename Protocol::resolver resolver_type; + typedef typename resolver_type::iterator iterator_type; + resolver_type resolver(detail::socket_streambuf_base::io_service_); + iterator_type i = resolver.resolve(query, ec_); + if (!ec_) + { + iterator_type end; + ec_ = boost::asio::error::host_not_found; + while (ec_ && i != end) + { + this->basic_socket<Protocol, StreamSocketService>::close(ec_); + + if (timer_state_ == timer_has_expired) + { + ec_ = boost::asio::error::operation_aborted; + return; + } + + io_handler handler = { this }; + this->basic_socket<Protocol, StreamSocketService>::async_connect( + *i, handler); + + ec_ = boost::asio::error::would_block; + this->get_service().get_io_service().reset(); + do this->get_service().get_io_service().run_one(); + while (ec_ == boost::asio::error::would_block); + + ++i; + } + } + } + + struct io_handler; + friend struct io_handler; + struct io_handler + { + basic_socket_streambuf* this_; + + void operator()(const boost::system::error_code& ec, + std::size_t bytes_transferred = 0) + { + this_->ec_ = ec; + this_->bytes_transferred_ = bytes_transferred; + } + }; + + struct timer_handler; + friend struct timer_handler; + struct timer_handler + { + basic_socket_streambuf* this_; + + void operator()(const boost::system::error_code&) + { + time_type now = traits_helper::now(); + + time_type expiry_time = this_->timer_service_->expires_at( + this_->timer_implementation_); + + if (traits_helper::less_than(now, expiry_time)) + { + this_->timer_state_ = timer_is_pending; + this_->timer_service_->async_wait(this_->timer_implementation_, *this); + } + else + { + this_->timer_state_ = timer_has_expired; + boost::system::error_code ec; + this_->basic_socket<Protocol, StreamSocketService>::close(ec); + } + } + }; + + void construct_timer() + { + if (timer_service_ == 0) + { + TimerService& timer_service = use_service<TimerService>( + detail::socket_streambuf_base::io_service_); + timer_service.construct(timer_implementation_); + timer_service_ = &timer_service; + } + } + + void destroy_timer() + { + if (timer_service_) + timer_service_->destroy(timer_implementation_); + } + + void start_timer() + { + if (timer_state_ != timer_is_pending) + { + timer_handler handler = { this }; + handler(boost::system::error_code()); + } + } + + enum { putback_max = 8 }; + enum { buffer_size = 512 }; + boost::asio::detail::array<char, buffer_size> get_buffer_; + boost::asio::detail::array<char, buffer_size> put_buffer_; + bool unbuffered_; + boost::system::error_code ec_; + std::size_t bytes_transferred_; + TimerService* timer_service_; + typename TimerService::implementation_type timer_implementation_; + enum state { no_timer, timer_is_pending, timer_has_expired } timer_state_; +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) +# undef BOOST_ASIO_PRIVATE_CONNECT_DEF +#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +#endif // !defined(BOOST_ASIO_NO_IOSTREAM) + +#endif // BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
diff --git a/boost/boost/asio/basic_stream_socket.hpp b/boost/boost/asio/basic_stream_socket.hpp new file mode 100644 index 0000000..44ce016 --- /dev/null +++ b/boost/boost/asio/basic_stream_socket.hpp
@@ -0,0 +1,854 @@ +// +// basic_stream_socket.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_STREAM_SOCKET_HPP +#define BOOST_ASIO_BASIC_STREAM_SOCKET_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/async_result.hpp> +#include <boost/asio/basic_socket.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/stream_socket_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides stream-oriented socket functionality. +/** + * The basic_stream_socket class template provides asynchronous and blocking + * stream-oriented socket functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template <typename Protocol, + typename StreamSocketService = stream_socket_service<Protocol> > +class basic_stream_socket + : public basic_socket<Protocol, StreamSocketService> +{ +public: + /// (Deprecated: Use native_handle_type.) The native representation of a + /// socket. + typedef typename StreamSocketService::native_handle_type native_type; + + /// The native representation of a socket. + typedef typename StreamSocketService::native_handle_type native_handle_type; + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + /// Construct a basic_stream_socket without opening it. + /** + * This constructor creates a stream socket without opening it. The socket + * needs to be opened and then connected or accepted before data can be sent + * or received on it. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + */ + explicit basic_stream_socket(boost::asio::io_service& io_service) + : basic_socket<Protocol, StreamSocketService>(io_service) + { + } + + /// Construct and open a basic_stream_socket. + /** + * This constructor creates and opens a stream socket. The socket needs to be + * connected or accepted before data can be sent or received on it. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_socket(boost::asio::io_service& io_service, + const protocol_type& protocol) + : basic_socket<Protocol, StreamSocketService>(io_service, protocol) + { + } + + /// Construct a basic_stream_socket, opening it and binding it to the given + /// local endpoint. + /** + * This constructor creates a stream socket and automatically opens it bound + * to the specified endpoint on the local machine. The protocol used is the + * protocol associated with the given endpoint. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param endpoint An endpoint on the local machine to which the stream + * socket will be bound. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_socket(boost::asio::io_service& io_service, + const endpoint_type& endpoint) + : basic_socket<Protocol, StreamSocketService>(io_service, endpoint) + { + } + + /// Construct a basic_stream_socket on an existing native socket. + /** + * This constructor creates a stream socket object to hold an existing native + * socket. + * + * @param io_service The io_service object that the stream socket will use to + * dispatch handlers for any asynchronous operations performed on the socket. + * + * @param protocol An object specifying protocol parameters to be used. + * + * @param native_socket The new underlying socket implementation. + * + * @throws boost::system::system_error Thrown on failure. + */ + basic_stream_socket(boost::asio::io_service& io_service, + const protocol_type& protocol, const native_handle_type& native_socket) + : basic_socket<Protocol, StreamSocketService>( + io_service, protocol, native_socket) + { + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a basic_stream_socket from another. + /** + * This constructor moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(io_service&) constructor. + */ + basic_stream_socket(basic_stream_socket&& other) + : basic_socket<Protocol, StreamSocketService>( + BOOST_ASIO_MOVE_CAST(basic_stream_socket)(other)) + { + } + + /// Move-assign a basic_stream_socket from another. + /** + * This assignment operator moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(io_service&) constructor. + */ + basic_stream_socket& operator=(basic_stream_socket&& other) + { + basic_socket<Protocol, StreamSocketService>::operator=( + BOOST_ASIO_MOVE_CAST(basic_stream_socket)(other)); + return *this; + } + + /// Move-construct a basic_stream_socket from a socket of another protocol + /// type. + /** + * This constructor moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(io_service&) constructor. + */ + template <typename Protocol1, typename StreamSocketService1> + basic_stream_socket( + basic_stream_socket<Protocol1, StreamSocketService1>&& other, + typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0) + : basic_socket<Protocol, StreamSocketService>( + BOOST_ASIO_MOVE_CAST2(basic_stream_socket< + Protocol1, StreamSocketService1>)(other)) + { + } + + /// Move-assign a basic_stream_socket from a socket of another protocol type. + /** + * This assignment operator moves a stream socket from one object to another. + * + * @param other The other basic_stream_socket object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_socket(io_service&) constructor. + */ + template <typename Protocol1, typename StreamSocketService1> + typename enable_if<is_convertible<Protocol1, Protocol>::value, + basic_stream_socket>::type& operator=( + basic_stream_socket<Protocol1, StreamSocketService1>&& other) + { + basic_socket<Protocol, StreamSocketService>::operator=( + BOOST_ASIO_MOVE_CAST2(basic_stream_socket< + Protocol1, StreamSocketService1>)(other)); + return *this; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.send(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @returns The number of bytes sent. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.send(boost::asio::buffer(data, size), 0); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "send"); + return s; + } + + /// Send some data on the socket. + /** + * This function is used to send data on the stream socket. The function + * call will block until one or more bytes of the data has been sent + * successfully, or an until error occurs. + * + * @param buffers One or more data buffers to be sent on the socket. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes sent. Returns 0 if an error occurred. + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref write function if you need to ensure that all data + * is written before the blocking operation completes. + */ + template <typename ConstBufferSequence> + std::size_t send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->get_service().send( + this->get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send data on the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send( + this->get_implementation(), buffers, 0, + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Start an asynchronous send. + /** + * This function is used to asynchronously send data on the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be sent on the socket. Although + * the buffers object may be copied as necessary, ownership of the underlying + * memory blocks is retained by the caller, which must guarantee that they + * remain valid until the handler is called. + * + * @param flags Flags specifying how the send call is to be made. + * + * @param handler The handler to be called when the send operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes sent. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The send operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To send a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_send(boost::asio::buffer(data, size), 0, handler); + * @endcode + * See the @ref buffer documentation for information on sending multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(const ConstBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send( + this->get_implementation(), buffers, flags, + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on the socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @returns The number of bytes received. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.receive(boost::asio::buffer(data, size), 0); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, flags, ec); + boost::asio::detail::throw_error(ec, "receive"); + return s; + } + + /// Receive some data on a connected socket. + /** + * This function is used to receive data on the stream socket. The function + * call will block until one or more bytes of data has been received + * successfully, or until an error occurs. + * + * @param buffers One or more buffers into which the data will be received. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes received. Returns 0 if an error occurred. + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that the + * requested amount of data is read before the blocking operation completes. + */ + template <typename MutableBufferSequence> + std::size_t receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return this->get_service().receive( + this->get_implementation(), buffers, flags, ec); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the stream + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref async_read function if you need to ensure + * that the requested amount of data is received before the asynchronous + * operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Start an asynchronous receive. + /** + * This function is used to asynchronously receive data from the stream + * socket. The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be received. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param flags Flags specifying how the receive call is to be made. + * + * @param handler The handler to be called when the receive operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes received. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The receive operation may not receive all of the requested number of + * bytes. Consider using the @ref async_read function if you need to ensure + * that the requested amount of data is received before the asynchronous + * operation completes. + * + * @par Example + * To receive into a single data buffer use the @ref buffer function as + * follows: + * @code + * socket.async_receive(boost::asio::buffer(data, size), 0, handler); + * @endcode + * See the @ref buffer documentation for information on receiving into + * multiple buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(const MutableBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Write some data to the socket. + /** + * This function is used to write data to the stream socket. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the socket. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * socket.write_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().send( + this->get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "write_some"); + return s; + } + + /// Write some data to the socket. + /** + * This function is used to write data to the stream socket. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the socket. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->get_service().send(this->get_implementation(), buffers, 0, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more data buffers to be written to the socket. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the write operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_write_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_write_some(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WriteHandler. + BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + return this->get_service().async_send(this->get_implementation(), + buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Read some data from the socket. + /** + * This function is used to read data from the stream socket. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. An error code of + * boost::asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * socket.read_some(boost::asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers) + { + boost::system::error_code ec; + std::size_t s = this->get_service().receive( + this->get_implementation(), buffers, 0, ec); + boost::asio::detail::throw_error(ec, "read_some"); + return s; + } + + /// Read some data from the socket. + /** + * This function is used to read data from the stream socket. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return this->get_service().receive( + this->get_implementation(), buffers, 0, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream socket. + * The function call always returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the handler is called. + * + * @param handler The handler to be called when the read operation completes. + * Copies will be made of the handler as required. The function signature of + * the handler must be: + * @code void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * socket.async_read_some(boost::asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_read_some(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ReadHandler. + BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + return this->get_service().async_receive(this->get_implementation(), + buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_HPP
diff --git a/boost/boost/asio/basic_streambuf.hpp b/boost/boost/asio/basic_streambuf.hpp new file mode 100644 index 0000000..d8cb477 --- /dev/null +++ b/boost/boost/asio/basic_streambuf.hpp
@@ -0,0 +1,371 @@ +// +// basic_streambuf.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_STREAMBUF_HPP +#define BOOST_ASIO_BASIC_STREAMBUF_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_NO_IOSTREAM) + +#include <algorithm> +#include <cstring> +#include <stdexcept> +#include <streambuf> +#include <vector> +#include <boost/asio/basic_streambuf_fwd.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/asio/detail/limits.hpp> +#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/throw_exception.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Automatically resizable buffer class based on std::streambuf. +/** + * The @c basic_streambuf class is derived from @c std::streambuf to associate + * the streambuf's input and output sequences with one or more character + * arrays. These character arrays are internal to the @c basic_streambuf + * object, but direct access to the array elements is provided to permit them + * to be used efficiently with I/O operations. Characters written to the output + * sequence of a @c basic_streambuf object are appended to the input sequence + * of the same object. + * + * The @c basic_streambuf class's public interface is intended to permit the + * following implementation strategies: + * + * @li A single contiguous character array, which is reallocated as necessary + * to accommodate changes in the size of the character sequence. This is the + * implementation approach currently used in Asio. + * + * @li A sequence of one or more character arrays, where each array is of the + * same size. Additional character array objects are appended to the sequence + * to accommodate changes in the size of the character sequence. + * + * @li A sequence of one or more character arrays of varying sizes. Additional + * character array objects are appended to the sequence to accommodate changes + * in the size of the character sequence. + * + * The constructor for basic_streambuf accepts a @c size_t argument specifying + * the maximum of the sum of the sizes of the input sequence and output + * sequence. During the lifetime of the @c basic_streambuf object, the following + * invariant holds: + * @code size() <= max_size()@endcode + * Any member function that would, if successful, cause the invariant to be + * violated shall throw an exception of class @c std::length_error. + * + * The constructor for @c basic_streambuf takes an Allocator argument. A copy + * of this argument is used for any memory allocation performed, by the + * constructor and by all member functions, during the lifetime of each @c + * basic_streambuf object. + * + * @par Examples + * Writing directly from an streambuf to a socket: + * @code + * boost::asio::streambuf b; + * std::ostream os(&b); + * os << "Hello, World!\n"; + * + * // try sending some data in input sequence + * size_t n = sock.send(b.data()); + * + * b.consume(n); // sent data is removed from input sequence + * @endcode + * + * Reading from a socket directly into a streambuf: + * @code + * boost::asio::streambuf b; + * + * // reserve 512 bytes in output sequence + * boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512); + * + * size_t n = sock.receive(bufs); + * + * // received data is "committed" from output sequence to input sequence + * b.commit(n); + * + * std::istream is(&b); + * std::string s; + * is >> s; + * @endcode + */ +#if defined(GENERATING_DOCUMENTATION) +template <typename Allocator = std::allocator<char> > +#else +template <typename Allocator> +#endif +class basic_streambuf + : public std::streambuf, + private noncopyable +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The type used to represent the input sequence as a list of buffers. + typedef implementation_defined const_buffers_type; + + /// The type used to represent the output sequence as a list of buffers. + typedef implementation_defined mutable_buffers_type; +#else + typedef boost::asio::const_buffers_1 const_buffers_type; + typedef boost::asio::mutable_buffers_1 mutable_buffers_type; +#endif + + /// Construct a basic_streambuf object. + /** + * Constructs a streambuf with the specified maximum size. The initial size + * of the streambuf's input sequence is 0. + */ + explicit basic_streambuf( + std::size_t maximum_size = (std::numeric_limits<std::size_t>::max)(), + const Allocator& allocator = Allocator()) + : max_size_(maximum_size), + buffer_(allocator) + { + std::size_t pend = (std::min<std::size_t>)(max_size_, buffer_delta); + buffer_.resize((std::max<std::size_t>)(pend, 1)); + setg(&buffer_[0], &buffer_[0], &buffer_[0]); + setp(&buffer_[0], &buffer_[0] + pend); + } + + /// Get the size of the input sequence. + /** + * @returns The size of the input sequence. The value is equal to that + * calculated for @c s in the following code: + * @code + * size_t s = 0; + * const_buffers_type bufs = data(); + * const_buffers_type::const_iterator i = bufs.begin(); + * while (i != bufs.end()) + * { + * const_buffer buf(*i++); + * s += buffer_size(buf); + * } + * @endcode + */ + std::size_t size() const + { + return pptr() - gptr(); + } + + /// Get the maximum size of the basic_streambuf. + /** + * @returns The allowed maximum of the sum of the sizes of the input sequence + * and output sequence. + */ + std::size_t max_size() const + { + return max_size_; + } + + /// Get a list of buffers that represents the input sequence. + /** + * @returns An object of type @c const_buffers_type that satisfies + * ConstBufferSequence requirements, representing all character arrays in the + * input sequence. + * + * @note The returned object is invalidated by any @c basic_streambuf member + * function that modifies the input sequence or output sequence. + */ + const_buffers_type data() const + { + return boost::asio::buffer(boost::asio::const_buffer(gptr(), + (pptr() - gptr()) * sizeof(char_type))); + } + + /// Get a list of buffers that represents the output sequence, with the given + /// size. + /** + * Ensures that the output sequence can accommodate @c n characters, + * reallocating character array objects as necessary. + * + * @returns An object of type @c mutable_buffers_type that satisfies + * MutableBufferSequence requirements, representing character array objects + * at the start of the output sequence such that the sum of the buffer sizes + * is @c n. + * + * @throws std::length_error If <tt>size() + n > max_size()</tt>. + * + * @note The returned object is invalidated by any @c basic_streambuf member + * function that modifies the input sequence or output sequence. + */ + mutable_buffers_type prepare(std::size_t n) + { + reserve(n); + return boost::asio::buffer(boost::asio::mutable_buffer( + pptr(), n * sizeof(char_type))); + } + + /// Move characters from the output sequence to the input sequence. + /** + * Appends @c n characters from the start of the output sequence to the input + * sequence. The beginning of the output sequence is advanced by @c n + * characters. + * + * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and + * no intervening operations that modify the input or output sequence. + * + * @note If @c n is greater than the size of the output sequence, the entire + * output sequence is moved to the input sequence and no error is issued. + */ + void commit(std::size_t n) + { + if (pptr() + n > epptr()) + n = epptr() - pptr(); + pbump(static_cast<int>(n)); + setg(eback(), gptr(), pptr()); + } + + /// Remove characters from the input sequence. + /** + * Removes @c n characters from the beginning of the input sequence. + * + * @note If @c n is greater than the size of the input sequence, the entire + * input sequence is consumed and no error is issued. + */ + void consume(std::size_t n) + { + if (egptr() < pptr()) + setg(&buffer_[0], gptr(), pptr()); + if (gptr() + n > pptr()) + n = pptr() - gptr(); + gbump(static_cast<int>(n)); + } + +protected: + enum { buffer_delta = 128 }; + + /// Override std::streambuf behaviour. + /** + * Behaves according to the specification of @c std::streambuf::underflow(). + */ + int_type underflow() + { + if (gptr() < pptr()) + { + setg(&buffer_[0], gptr(), pptr()); + return traits_type::to_int_type(*gptr()); + } + else + { + return traits_type::eof(); + } + } + + /// Override std::streambuf behaviour. + /** + * Behaves according to the specification of @c std::streambuf::overflow(), + * with the specialisation that @c std::length_error is thrown if appending + * the character to the input sequence would require the condition + * <tt>size() > max_size()</tt> to be true. + */ + int_type overflow(int_type c) + { + if (!traits_type::eq_int_type(c, traits_type::eof())) + { + if (pptr() == epptr()) + { + std::size_t buffer_size = pptr() - gptr(); + if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta) + { + reserve(max_size_ - buffer_size); + } + else + { + reserve(buffer_delta); + } + } + + *pptr() = traits_type::to_char_type(c); + pbump(1); + return c; + } + + return traits_type::not_eof(c); + } + + void reserve(std::size_t n) + { + // Get current stream positions as offsets. + std::size_t gnext = gptr() - &buffer_[0]; + std::size_t pnext = pptr() - &buffer_[0]; + std::size_t pend = epptr() - &buffer_[0]; + + // Check if there is already enough space in the put area. + if (n <= pend - pnext) + { + return; + } + + // Shift existing contents of get area to start of buffer. + if (gnext > 0) + { + pnext -= gnext; + std::memmove(&buffer_[0], &buffer_[0] + gnext, pnext); + } + + // Ensure buffer is large enough to hold at least the specified size. + if (n > pend - pnext) + { + if (n <= max_size_ && pnext <= max_size_ - n) + { + pend = pnext + n; + buffer_.resize((std::max<std::size_t>)(pend, 1)); + } + else + { + std::length_error ex("boost::asio::streambuf too long"); + boost::asio::detail::throw_exception(ex); + } + } + + // Update stream positions. + setg(&buffer_[0], &buffer_[0], &buffer_[0] + pnext); + setp(&buffer_[0] + pnext, &buffer_[0] + pend); + } + +private: + std::size_t max_size_; + std::vector<char_type, Allocator> buffer_; + + // Helper function to get the preferred size for reading data. + friend std::size_t read_size_helper( + basic_streambuf& sb, std::size_t max_size) + { + return std::min<std::size_t>( + std::max<std::size_t>(512, sb.buffer_.capacity() - sb.size()), + std::min<std::size_t>(max_size, sb.max_size() - sb.size())); + } +}; + +// Helper function to get the preferred size for reading data. Used for any +// user-provided specialisations of basic_streambuf. +template <typename Allocator> +inline std::size_t read_size_helper( + basic_streambuf<Allocator>& sb, std::size_t max_size) +{ + return std::min<std::size_t>(512, + std::min<std::size_t>(max_size, sb.max_size() - sb.size())); +} + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // !defined(BOOST_ASIO_NO_IOSTREAM) + +#endif // BOOST_ASIO_BASIC_STREAMBUF_HPP
diff --git a/boost/boost/asio/basic_streambuf_fwd.hpp b/boost/boost/asio/basic_streambuf_fwd.hpp new file mode 100644 index 0000000..5026aba --- /dev/null +++ b/boost/boost/asio/basic_streambuf_fwd.hpp
@@ -0,0 +1,35 @@ +// +// basic_streambuf_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_STREAMBUF_FWD_HPP +#define BOOST_ASIO_BASIC_STREAMBUF_FWD_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_NO_IOSTREAM) + +#include <memory> + +namespace boost { +namespace asio { + +template <typename Allocator = std::allocator<char> > +class basic_streambuf; + +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_ASIO_NO_IOSTREAM) + +#endif // BOOST_ASIO_BASIC_STREAMBUF_FWD_HPP
diff --git a/boost/boost/asio/basic_waitable_timer.hpp b/boost/boost/asio/basic_waitable_timer.hpp new file mode 100644 index 0000000..3f63c78 --- /dev/null +++ b/boost/boost/asio/basic_waitable_timer.hpp
@@ -0,0 +1,521 @@ +// +// basic_waitable_timer.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP +#define BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/basic_io_object.hpp> +#include <boost/asio/detail/handler_type_requirements.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/wait_traits.hpp> +#include <boost/asio/waitable_timer_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Provides waitable timer functionality. +/** + * The basic_waitable_timer class template provides the ability to perform a + * blocking or asynchronous wait for a timer to expire. + * + * A waitable timer is always in one of two states: "expired" or "not expired". + * If the wait() or async_wait() function is called on an expired timer, the + * wait operation will complete immediately. + * + * Most applications will use one of the boost::asio::steady_timer, + * boost::asio::system_timer or boost::asio::high_resolution_timer typedefs. + * + * @note This waitable timer functionality is for use with the C++11 standard + * library's @c <chrono> facility, or with the Boost.Chrono library. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Examples + * Performing a blocking wait (C++11): + * @code + * // Construct a timer without setting an expiry time. + * boost::asio::steady_timer timer(io_service); + * + * // Set an expiry time relative to now. + * timer.expires_from_now(std::chrono::seconds(5)); + * + * // Wait for the timer to expire. + * timer.wait(); + * @endcode + * + * @par + * Performing an asynchronous wait (C++11): + * @code + * void handler(const boost::system::error_code& error) + * { + * if (!error) + * { + * // Timer expired. + * } + * } + * + * ... + * + * // Construct a timer with an absolute expiry time. + * boost::asio::steady_timer timer(io_service, + * std::chrono::steady_clock::now() + std::chrono::seconds(60)); + * + * // Start an asynchronous wait. + * timer.async_wait(handler); + * @endcode + * + * @par Changing an active waitable timer's expiry time + * + * Changing the expiry time of a timer while there are pending asynchronous + * waits causes those wait operations to be cancelled. To ensure that the action + * associated with the timer is performed only once, use something like this: + * used: + * + * @code + * void on_some_event() + * { + * if (my_timer.expires_from_now(seconds(5)) > 0) + * { + * // We managed to cancel the timer. Start new asynchronous wait. + * my_timer.async_wait(on_timeout); + * } + * else + * { + * // Too late, timer has already expired! + * } + * } + * + * void on_timeout(const boost::system::error_code& e) + * { + * if (e != boost::asio::error::operation_aborted) + * { + * // Timer was not cancelled, take necessary action. + * } + * } + * @endcode + * + * @li The boost::asio::basic_waitable_timer::expires_from_now() function + * cancels any pending asynchronous waits, and returns the number of + * asynchronous waits that were cancelled. If it returns 0 then you were too + * late and the wait handler has already been executed, or will soon be + * executed. If it returns 1 then the wait handler was successfully cancelled. + * + * @li If a wait handler is cancelled, the boost::system::error_code passed to + * it contains the value boost::asio::error::operation_aborted. + */ +template <typename Clock, + typename WaitTraits = boost::asio::wait_traits<Clock>, + typename WaitableTimerService = waitable_timer_service<Clock, WaitTraits> > +class basic_waitable_timer + : public basic_io_object<WaitableTimerService> +{ +public: + /// The clock type. + typedef Clock clock_type; + + /// The duration type of the clock. + typedef typename clock_type::duration duration; + + /// The time point type of the clock. + typedef typename clock_type::time_point time_point; + + /// The wait traits type. + typedef WaitTraits traits_type; + + /// Constructor. + /** + * This constructor creates a timer without setting an expiry time. The + * expires_at() or expires_from_now() functions must be called to set an + * expiry time before the timer can be waited on. + * + * @param io_service The io_service object that the timer will use to dispatch + * handlers for any asynchronous operations performed on the timer. + */ + explicit basic_waitable_timer(boost::asio::io_service& io_service) + : basic_io_object<WaitableTimerService>(io_service) + { + } + + /// Constructor to set a particular expiry time as an absolute time. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param io_service The io_service object that the timer will use to dispatch + * handlers for any asynchronous operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, expressed + * as an absolute time. + */ + basic_waitable_timer(boost::asio::io_service& io_service, + const time_point& expiry_time) + : basic_io_object<WaitableTimerService>(io_service) + { + boost::system::error_code ec; + this->service.expires_at(this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_at"); + } + + /// Constructor to set a particular expiry time relative to now. + /** + * This constructor creates a timer and sets the expiry time. + * + * @param io_service The io_service object that the timer will use to dispatch + * handlers for any asynchronous operations performed on the timer. + * + * @param expiry_time The expiry time to be used for the timer, relative to + * now. + */ + basic_waitable_timer(boost::asio::io_service& io_service, + const duration& expiry_time) + : basic_io_object<WaitableTimerService>(io_service) + { + boost::system::error_code ec; + this->service.expires_from_now(this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_from_now"); + } + + /// Cancel any asynchronous operations that are waiting on the timer. + /** + * This function forces the completion of any pending asynchronous wait + * operations against the timer. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @return The number of asynchronous operations that were cancelled. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note If the timer has already expired when cancel() is called, then the + * handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t cancel() + { + boost::system::error_code ec; + std::size_t s = this->service.cancel(this->implementation, ec); + boost::asio::detail::throw_error(ec, "cancel"); + return s; + } + + /// Cancel any asynchronous operations that are waiting on the timer. + /** + * This function forces the completion of any pending asynchronous wait + * operations against the timer. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. + * + * @note If the timer has already expired when cancel() is called, then the + * handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t cancel(boost::system::error_code& ec) + { + return this->service.cancel(this->implementation, ec); + } + + /// Cancels one asynchronous operation that is waiting on the timer. + /** + * This function forces the completion of one pending asynchronous wait + * operation against the timer. Handlers are cancelled in FIFO order. The + * handler for the cancelled operation will be invoked with the + * boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @return The number of asynchronous operations that were cancelled. That is, + * either 0 or 1. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note If the timer has already expired when cancel_one() is called, then + * the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t cancel_one() + { + boost::system::error_code ec; + std::size_t s = this->service.cancel_one(this->implementation, ec); + boost::asio::detail::throw_error(ec, "cancel_one"); + return s; + } + + /// Cancels one asynchronous operation that is waiting on the timer. + /** + * This function forces the completion of one pending asynchronous wait + * operation against the timer. Handlers are cancelled in FIFO order. The + * handler for the cancelled operation will be invoked with the + * boost::asio::error::operation_aborted error code. + * + * Cancelling the timer does not change the expiry time. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. That is, + * either 0 or 1. + * + * @note If the timer has already expired when cancel_one() is called, then + * the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t cancel_one(boost::system::error_code& ec) + { + return this->service.cancel_one(this->implementation, ec); + } + + /// Get the timer's expiry time as an absolute time. + /** + * This function may be used to obtain the timer's current expiry time. + * Whether the timer has expired or not does not affect this value. + */ + time_point expires_at() const + { + return this->service.expires_at(this->implementation); + } + + /// Set the timer's expiry time as an absolute time. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @return The number of asynchronous operations that were cancelled. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note If the timer has already expired when expires_at() is called, then + * the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t expires_at(const time_point& expiry_time) + { + boost::system::error_code ec; + std::size_t s = this->service.expires_at( + this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_at"); + return s; + } + + /// Set the timer's expiry time as an absolute time. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. + * + * @note If the timer has already expired when expires_at() is called, then + * the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t expires_at(const time_point& expiry_time, + boost::system::error_code& ec) + { + return this->service.expires_at(this->implementation, expiry_time, ec); + } + + /// Get the timer's expiry time relative to now. + /** + * This function may be used to obtain the timer's current expiry time. + * Whether the timer has expired or not does not affect this value. + */ + duration expires_from_now() const + { + return this->service.expires_from_now(this->implementation); + } + + /// Set the timer's expiry time relative to now. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @return The number of asynchronous operations that were cancelled. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note If the timer has already expired when expires_from_now() is called, + * then the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t expires_from_now(const duration& expiry_time) + { + boost::system::error_code ec; + std::size_t s = this->service.expires_from_now( + this->implementation, expiry_time, ec); + boost::asio::detail::throw_error(ec, "expires_from_now"); + return s; + } + + /// Set the timer's expiry time relative to now. + /** + * This function sets the expiry time. Any pending asynchronous wait + * operations will be cancelled. The handler for each cancelled operation will + * be invoked with the boost::asio::error::operation_aborted error code. + * + * @param expiry_time The expiry time to be used for the timer. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return The number of asynchronous operations that were cancelled. + * + * @note If the timer has already expired when expires_from_now() is called, + * then the handlers for asynchronous wait operations will: + * + * @li have already been invoked; or + * + * @li have been queued for invocation in the near future. + * + * These handlers can no longer be cancelled, and therefore are passed an + * error code that indicates the successful completion of the wait operation. + */ + std::size_t expires_from_now(const duration& expiry_time, + boost::system::error_code& ec) + { + return this->service.expires_from_now( + this->implementation, expiry_time, ec); + } + + /// Perform a blocking wait on the timer. + /** + * This function is used to wait for the timer to expire. This function + * blocks and does not return until the timer has expired. + * + * @throws boost::system::system_error Thrown on failure. + */ + void wait() + { + boost::system::error_code ec; + this->service.wait(this->implementation, ec); + boost::asio::detail::throw_error(ec, "wait"); + } + + /// Perform a blocking wait on the timer. + /** + * This function is used to wait for the timer to expire. This function + * blocks and does not return until the timer has expired. + * + * @param ec Set to indicate what error occurred, if any. + */ + void wait(boost::system::error_code& ec) + { + this->service.wait(this->implementation, ec); + } + + /// Start an asynchronous wait on the timer. + /** + * This function may be used to initiate an asynchronous wait against the + * timer. It always returns immediately. + * + * For each call to async_wait(), the supplied handler will be called exactly + * once. The handler will be called when: + * + * @li The timer has expired. + * + * @li The timer was cancelled, in which case the handler is passed the error + * code boost::asio::error::operation_aborted. + * + * @param handler The handler to be called when the timer expires. Copies + * will be made of the handler as required. The function signature of the + * handler must be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + */ + template <typename WaitHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, + void (boost::system::error_code)) + async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a WaitHandler. + BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check; + + return this->service.async_wait(this->implementation, + BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); + } +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
diff --git a/boost/boost/asio/buffer.hpp b/boost/boost/asio/buffer.hpp new file mode 100644 index 0000000..729a31b --- /dev/null +++ b/boost/boost/asio/buffer.hpp
@@ -0,0 +1,2241 @@ +// +// buffer.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFER_HPP +#define BOOST_ASIO_BUFFER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <cstring> +#include <string> +#include <vector> +#include <boost/asio/detail/array_fwd.hpp> + +#if defined(BOOST_ASIO_MSVC) +# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0) +# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) +# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING +# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) +# endif // defined(_HAS_ITERATOR_DEBUGGING) +#endif // defined(BOOST_ASIO_MSVC) + +#if defined(__GNUC__) +# if defined(_GLIBCXX_DEBUG) +# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) +# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING +# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING) +# endif // defined(_GLIBCXX_DEBUG) +#endif // defined(__GNUC__) + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +# include <boost/asio/detail/function.hpp> +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + +#if defined(BOOST_ASIO_HAS_BOOST_WORKAROUND) +# include <boost/detail/workaround.hpp> +# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \ + || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) +# define BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND +# endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) + // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) +#endif // defined(BOOST_ASIO_HAS_BOOST_WORKAROUND) + +#if defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) +# include <boost/asio/detail/type_traits.hpp> +#endif // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +class mutable_buffer; +class const_buffer; + +namespace detail { +void* buffer_cast_helper(const mutable_buffer&); +const void* buffer_cast_helper(const const_buffer&); +std::size_t buffer_size_helper(const mutable_buffer&); +std::size_t buffer_size_helper(const const_buffer&); +} // namespace detail + +/// Holds a buffer that can be modified. +/** + * The mutable_buffer class provides a safe representation of a buffer that can + * be modified. It does not own the underlying data, and so is cheap to copy or + * assign. + * + * @par Accessing Buffer Contents + * + * The contents of a buffer may be accessed using the @ref buffer_size + * and @ref buffer_cast functions: + * + * @code boost::asio::mutable_buffer b1 = ...; + * std::size_t s1 = boost::asio::buffer_size(b1); + * unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1); + * @endcode + * + * The boost::asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + */ +class mutable_buffer +{ +public: + /// Construct an empty buffer. + mutable_buffer() + : data_(0), + size_(0) + { + } + + /// Construct a buffer to represent a given memory range. + mutable_buffer(void* data, std::size_t size) + : data_(data), + size_(size) + { + } + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + mutable_buffer(void* data, std::size_t size, + boost::asio::detail::function<void()> debug_check) + : data_(data), + size_(size), + debug_check_(debug_check) + { + } + + const boost::asio::detail::function<void()>& get_debug_check() const + { + return debug_check_; + } +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + +private: + friend void* boost::asio::detail::buffer_cast_helper( + const mutable_buffer& b); + friend std::size_t boost::asio::detail::buffer_size_helper( + const mutable_buffer& b); + + void* data_; + std::size_t size_; + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + boost::asio::detail::function<void()> debug_check_; +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING +}; + +namespace detail { + +inline void* buffer_cast_helper(const mutable_buffer& b) +{ +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + if (b.size_ && b.debug_check_) + b.debug_check_(); +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + return b.data_; +} + +inline std::size_t buffer_size_helper(const mutable_buffer& b) +{ + return b.size_; +} + +} // namespace detail + +/// Adapts a single modifiable buffer so that it meets the requirements of the +/// MutableBufferSequence concept. +class mutable_buffers_1 + : public mutable_buffer +{ +public: + /// The type for each element in the list of buffers. + typedef mutable_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const mutable_buffer* const_iterator; + + /// Construct to represent a given memory range. + mutable_buffers_1(void* data, std::size_t size) + : mutable_buffer(data, size) + { + } + + /// Construct to represent a single modifiable buffer. + explicit mutable_buffers_1(const mutable_buffer& b) + : mutable_buffer(b) + { + } + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return this; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return begin() + 1; + } +}; + +/// Holds a buffer that cannot be modified. +/** + * The const_buffer class provides a safe representation of a buffer that cannot + * be modified. It does not own the underlying data, and so is cheap to copy or + * assign. + * + * @par Accessing Buffer Contents + * + * The contents of a buffer may be accessed using the @ref buffer_size + * and @ref buffer_cast functions: + * + * @code boost::asio::const_buffer b1 = ...; + * std::size_t s1 = boost::asio::buffer_size(b1); + * const unsigned char* p1 = boost::asio::buffer_cast<const unsigned char*>(b1); + * @endcode + * + * The boost::asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + */ +class const_buffer +{ +public: + /// Construct an empty buffer. + const_buffer() + : data_(0), + size_(0) + { + } + + /// Construct a buffer to represent a given memory range. + const_buffer(const void* data, std::size_t size) + : data_(data), + size_(size) + { + } + + /// Construct a non-modifiable buffer from a modifiable one. + const_buffer(const mutable_buffer& b) + : data_(boost::asio::detail::buffer_cast_helper(b)), + size_(boost::asio::detail::buffer_size_helper(b)) +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , debug_check_(b.get_debug_check()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + { + } + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + const_buffer(const void* data, std::size_t size, + boost::asio::detail::function<void()> debug_check) + : data_(data), + size_(size), + debug_check_(debug_check) + { + } + + const boost::asio::detail::function<void()>& get_debug_check() const + { + return debug_check_; + } +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + +private: + friend const void* boost::asio::detail::buffer_cast_helper( + const const_buffer& b); + friend std::size_t boost::asio::detail::buffer_size_helper( + const const_buffer& b); + + const void* data_; + std::size_t size_; + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + boost::asio::detail::function<void()> debug_check_; +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING +}; + +namespace detail { + +inline const void* buffer_cast_helper(const const_buffer& b) +{ +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + if (b.size_ && b.debug_check_) + b.debug_check_(); +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + return b.data_; +} + +inline std::size_t buffer_size_helper(const const_buffer& b) +{ + return b.size_; +} + +} // namespace detail + +/// Adapts a single non-modifiable buffer so that it meets the requirements of +/// the ConstBufferSequence concept. +class const_buffers_1 + : public const_buffer +{ +public: + /// The type for each element in the list of buffers. + typedef const_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const const_buffer* const_iterator; + + /// Construct to represent a given memory range. + const_buffers_1(const void* data, std::size_t size) + : const_buffer(data, size) + { + } + + /// Construct to represent a single non-modifiable buffer. + explicit const_buffers_1(const const_buffer& b) + : const_buffer(b) + { + } + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return this; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return begin() + 1; + } +}; + +/// An implementation of both the ConstBufferSequence and MutableBufferSequence +/// concepts to represent a null buffer sequence. +class null_buffers +{ +public: + /// The type for each element in the list of buffers. + typedef mutable_buffer value_type; + + /// A random-access iterator type that may be used to read elements. + typedef const mutable_buffer* const_iterator; + + /// Get a random-access iterator to the first element. + const_iterator begin() const + { + return &buf_; + } + + /// Get a random-access iterator for one past the last element. + const_iterator end() const + { + return &buf_; + } + +private: + mutable_buffer buf_; +}; + +/** @defgroup buffer_size boost::asio::buffer_size + * + * @brief The boost::asio::buffer_size function determines the total number of + * bytes in a buffer or buffer sequence. + */ +/*@{*/ + +/// Get the number of bytes in a modifiable buffer. +inline std::size_t buffer_size(const mutable_buffer& b) +{ + return detail::buffer_size_helper(b); +} + +/// Get the number of bytes in a modifiable buffer. +inline std::size_t buffer_size(const mutable_buffers_1& b) +{ + return detail::buffer_size_helper(b); +} + +/// Get the number of bytes in a non-modifiable buffer. +inline std::size_t buffer_size(const const_buffer& b) +{ + return detail::buffer_size_helper(b); +} + +/// Get the number of bytes in a non-modifiable buffer. +inline std::size_t buffer_size(const const_buffers_1& b) +{ + return detail::buffer_size_helper(b); +} + +/// Get the total number of bytes in a buffer sequence. +/** + * The @c BufferSequence template parameter may meet either of the @c + * ConstBufferSequence or @c MutableBufferSequence type requirements. + */ +template <typename BufferSequence> +inline std::size_t buffer_size(const BufferSequence& b) +{ + std::size_t total_buffer_size = 0; + + typename BufferSequence::const_iterator iter = b.begin(); + typename BufferSequence::const_iterator end = b.end(); + for (; iter != end; ++iter) + total_buffer_size += detail::buffer_size_helper(*iter); + + return total_buffer_size; +} + +/*@}*/ + +/** @defgroup buffer_cast boost::asio::buffer_cast + * + * @brief The boost::asio::buffer_cast function is used to obtain a pointer to + * the underlying memory region associated with a buffer. + * + * @par Examples: + * + * To access the memory of a non-modifiable buffer, use: + * @code boost::asio::const_buffer b1 = ...; + * const unsigned char* p1 = boost::asio::buffer_cast<const unsigned char*>(b1); + * @endcode + * + * To access the memory of a modifiable buffer, use: + * @code boost::asio::mutable_buffer b2 = ...; + * unsigned char* p2 = boost::asio::buffer_cast<unsigned char*>(b2); + * @endcode + * + * The boost::asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + */ +/*@{*/ + +/// Cast a non-modifiable buffer to a specified pointer to POD type. +template <typename PointerToPodType> +inline PointerToPodType buffer_cast(const mutable_buffer& b) +{ + return static_cast<PointerToPodType>(detail::buffer_cast_helper(b)); +} + +/// Cast a non-modifiable buffer to a specified pointer to POD type. +template <typename PointerToPodType> +inline PointerToPodType buffer_cast(const const_buffer& b) +{ + return static_cast<PointerToPodType>(detail::buffer_cast_helper(b)); +} + +/*@}*/ + +/// Create a new modifiable buffer that is offset from the start of another. +/** + * @relates mutable_buffer + */ +inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start) +{ + if (start > buffer_size(b)) + return mutable_buffer(); + char* new_data = buffer_cast<char*>(b) + start; + std::size_t new_size = buffer_size(b) - start; + return mutable_buffer(new_data, new_size +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); +} + +/// Create a new modifiable buffer that is offset from the start of another. +/** + * @relates mutable_buffer + */ +inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b) +{ + if (start > buffer_size(b)) + return mutable_buffer(); + char* new_data = buffer_cast<char*>(b) + start; + std::size_t new_size = buffer_size(b) - start; + return mutable_buffer(new_data, new_size +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); +} + +/// Create a new non-modifiable buffer that is offset from the start of another. +/** + * @relates const_buffer + */ +inline const_buffer operator+(const const_buffer& b, std::size_t start) +{ + if (start > buffer_size(b)) + return const_buffer(); + const char* new_data = buffer_cast<const char*>(b) + start; + std::size_t new_size = buffer_size(b) - start; + return const_buffer(new_data, new_size +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); +} + +/// Create a new non-modifiable buffer that is offset from the start of another. +/** + * @relates const_buffer + */ +inline const_buffer operator+(std::size_t start, const const_buffer& b) +{ + if (start > buffer_size(b)) + return const_buffer(); + const char* new_data = buffer_cast<const char*>(b) + start; + std::size_t new_size = buffer_size(b) - start; + return const_buffer(new_data, new_size +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + ); +} + +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) +namespace detail { + +template <typename Iterator> +class buffer_debug_check +{ +public: + buffer_debug_check(Iterator iter) + : iter_(iter) + { + } + + ~buffer_debug_check() + { +#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC == 1400) + // MSVC 8's string iterator checking may crash in a std::string::iterator + // object's destructor when the iterator points to an already-destroyed + // std::string object, unless the iterator is cleared first. + iter_ = Iterator(); +#endif // defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC == 1400) + } + + void operator()() + { + *iter_; + } + +private: + Iterator iter_; +}; + +} // namespace detail +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + +/** @defgroup buffer boost::asio::buffer + * + * @brief The boost::asio::buffer function is used to create a buffer object to + * represent raw memory, an array of POD elements, a vector of POD elements, + * or a std::string. + * + * A buffer object represents a contiguous region of memory as a 2-tuple + * consisting of a pointer and size in bytes. A tuple of the form <tt>{void*, + * size_t}</tt> specifies a mutable (modifiable) region of memory. Similarly, a + * tuple of the form <tt>{const void*, size_t}</tt> specifies a const + * (non-modifiable) region of memory. These two forms correspond to the classes + * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion + * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the + * opposite conversion is not permitted. + * + * The simplest use case involves reading or writing a single buffer of a + * specified size: + * + * @code sock.send(boost::asio::buffer(data, size)); @endcode + * + * In the above example, the return value of boost::asio::buffer meets the + * requirements of the ConstBufferSequence concept so that it may be directly + * passed to the socket's write function. A buffer created for modifiable + * memory also meets the requirements of the MutableBufferSequence concept. + * + * An individual buffer may be created from a builtin array, std::vector, + * std::array or boost::array of POD elements. This helps prevent buffer + * overruns by automatically determining the size of the buffer: + * + * @code char d1[128]; + * size_t bytes_transferred = sock.receive(boost::asio::buffer(d1)); + * + * std::vector<char> d2(128); + * bytes_transferred = sock.receive(boost::asio::buffer(d2)); + * + * std::array<char, 128> d3; + * bytes_transferred = sock.receive(boost::asio::buffer(d3)); + * + * boost::array<char, 128> d4; + * bytes_transferred = sock.receive(boost::asio::buffer(d4)); @endcode + * + * In all three cases above, the buffers created are exactly 128 bytes long. + * Note that a vector is @e never automatically resized when creating or using + * a buffer. The buffer size is determined using the vector's <tt>size()</tt> + * member function, and not its capacity. + * + * @par Accessing Buffer Contents + * + * The contents of a buffer may be accessed using the @ref buffer_size and + * @ref buffer_cast functions: + * + * @code boost::asio::mutable_buffer b1 = ...; + * std::size_t s1 = boost::asio::buffer_size(b1); + * unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1); + * + * boost::asio::const_buffer b2 = ...; + * std::size_t s2 = boost::asio::buffer_size(b2); + * const void* p2 = boost::asio::buffer_cast<const void*>(b2); @endcode + * + * The boost::asio::buffer_cast function permits violations of type safety, so + * uses of it in application code should be carefully considered. + * + * For convenience, the @ref buffer_size function also works on buffer + * sequences (that is, types meeting the ConstBufferSequence or + * MutableBufferSequence type requirements). In this case, the function returns + * the total size of all buffers in the sequence. + * + * @par Buffer Copying + * + * The @ref buffer_copy function may be used to copy raw bytes between + * individual buffers and buffer sequences. + * + * In particular, when used with the @ref buffer_size, the @ref buffer_copy + * function can be used to linearise a sequence of buffers. For example: + * + * @code vector<const_buffer> buffers = ...; + * + * vector<unsigned char> data(boost::asio::buffer_size(buffers)); + * boost::asio::buffer_copy(boost::asio::buffer(data), buffers); @endcode + * + * Note that @ref buffer_copy is implemented in terms of @c memcpy, and + * consequently it cannot be used to copy between overlapping memory regions. + * + * @par Buffer Invalidation + * + * A buffer object does not have any ownership of the memory it refers to. It + * is the responsibility of the application to ensure the memory region remains + * valid until it is no longer required for an I/O operation. When the memory + * is no longer available, the buffer is said to have been invalidated. + * + * For the boost::asio::buffer overloads that accept an argument of type + * std::vector, the buffer objects returned are invalidated by any vector + * operation that also invalidates all references, pointers and iterators + * referring to the elements in the sequence (C++ Std, 23.2.4) + * + * For the boost::asio::buffer overloads that accept an argument of type + * std::basic_string, the buffer objects returned are invalidated according to + * the rules defined for invalidation of references, pointers and iterators + * referring to elements of the sequence (C++ Std, 21.3). + * + * @par Buffer Arithmetic + * + * Buffer objects may be manipulated using simple arithmetic in a safe way + * which helps prevent buffer overruns. Consider an array initialised as + * follows: + * + * @code boost::array<char, 6> a = { 'a', 'b', 'c', 'd', 'e' }; @endcode + * + * A buffer object @c b1 created using: + * + * @code b1 = boost::asio::buffer(a); @endcode + * + * represents the entire array, <tt>{ 'a', 'b', 'c', 'd', 'e' }</tt>. An + * optional second argument to the boost::asio::buffer function may be used to + * limit the size, in bytes, of the buffer: + * + * @code b2 = boost::asio::buffer(a, 3); @endcode + * + * such that @c b2 represents the data <tt>{ 'a', 'b', 'c' }</tt>. Even if the + * size argument exceeds the actual size of the array, the size of the buffer + * object created will be limited to the array size. + * + * An offset may be applied to an existing buffer to create a new one: + * + * @code b3 = b1 + 2; @endcode + * + * where @c b3 will set to represent <tt>{ 'c', 'd', 'e' }</tt>. If the offset + * exceeds the size of the existing buffer, the newly created buffer will be + * empty. + * + * Both an offset and size may be specified to create a buffer that corresponds + * to a specific range of bytes within an existing buffer: + * + * @code b4 = boost::asio::buffer(b1 + 1, 3); @endcode + * + * so that @c b4 will refer to the bytes <tt>{ 'b', 'c', 'd' }</tt>. + * + * @par Buffers and Scatter-Gather I/O + * + * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple + * buffer objects may be assigned into a container that supports the + * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts: + * + * @code + * char d1[128]; + * std::vector<char> d2(128); + * boost::array<char, 128> d3; + * + * boost::array<mutable_buffer, 3> bufs1 = { + * boost::asio::buffer(d1), + * boost::asio::buffer(d2), + * boost::asio::buffer(d3) }; + * bytes_transferred = sock.receive(bufs1); + * + * std::vector<const_buffer> bufs2; + * bufs2.push_back(boost::asio::buffer(d1)); + * bufs2.push_back(boost::asio::buffer(d2)); + * bufs2.push_back(boost::asio::buffer(d3)); + * bytes_transferred = sock.send(bufs2); @endcode + */ +/*@{*/ + +/// Create a new modifiable buffer from an existing buffer. +/** + * @returns <tt>mutable_buffers_1(b)</tt>. + */ +inline mutable_buffers_1 buffer(const mutable_buffer& b) +{ + return mutable_buffers_1(b); +} + +/// Create a new modifiable buffer from an existing buffer. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * buffer_cast<void*>(b), + * min(buffer_size(b), max_size_in_bytes)); @endcode + */ +inline mutable_buffers_1 buffer(const mutable_buffer& b, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(buffer_cast<void*>(b), + buffer_size(b) < max_size_in_bytes + ? buffer_size(b) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer from an existing buffer. +/** + * @returns <tt>const_buffers_1(b)</tt>. + */ +inline const_buffers_1 buffer(const const_buffer& b) +{ + return const_buffers_1(b); +} + +/// Create a new non-modifiable buffer from an existing buffer. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * buffer_cast<const void*>(b), + * min(buffer_size(b), max_size_in_bytes)); @endcode + */ +inline const_buffers_1 buffer(const const_buffer& b, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(buffer_cast<const void*>(b), + buffer_size(b) < max_size_in_bytes + ? buffer_size(b) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , b.get_debug_check() +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new modifiable buffer that represents the given memory range. +/** + * @returns <tt>mutable_buffers_1(data, size_in_bytes)</tt>. + */ +inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes) +{ + return mutable_buffers_1(mutable_buffer(data, size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given memory range. +/** + * @returns <tt>const_buffers_1(data, size_in_bytes)</tt>. + */ +inline const_buffers_1 buffer(const void* data, + std::size_t size_in_bytes) +{ + return const_buffers_1(const_buffer(data, size_in_bytes)); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * static_cast<void*>(data), + * N * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(PodType (&data)[N]) +{ + return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType))); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * static_cast<void*>(data), + * min(N * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(PodType (&data)[N], + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data, + N * sizeof(PodType) < max_size_in_bytes + ? N * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * static_cast<const void*>(data), + * N * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const PodType (&data)[N]) +{ + return const_buffers_1(const_buffer(data, N * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * static_cast<const void*>(data), + * min(N * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const PodType (&data)[N], + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data, + N * sizeof(PodType) < max_size_in_bytes + ? N * sizeof(PodType) : max_size_in_bytes)); +} + +#if defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) + +// Borland C++ and Sun Studio think the overloads: +// +// unspecified buffer(boost::array<PodType, N>& array ...); +// +// and +// +// unspecified buffer(boost::array<const PodType, N>& array ...); +// +// are ambiguous. This will be worked around by using a buffer_types traits +// class that contains typedefs for the appropriate buffer and container +// classes, based on whether PodType is const or non-const. + +namespace detail { + +template <bool IsConst> +struct buffer_types_base; + +template <> +struct buffer_types_base<false> +{ + typedef mutable_buffer buffer_type; + typedef mutable_buffers_1 container_type; +}; + +template <> +struct buffer_types_base<true> +{ + typedef const_buffer buffer_type; + typedef const_buffers_1 container_type; +}; + +template <typename PodType> +struct buffer_types + : public buffer_types_base<is_const<PodType>::value> +{ +}; + +} // namespace detail + +template <typename PodType, std::size_t N> +inline typename detail::buffer_types<PodType>::container_type +buffer(boost::array<PodType, N>& data) +{ + typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type + buffer_type; + typedef typename boost::asio::detail::buffer_types<PodType>::container_type + container_type; + return container_type( + buffer_type(data.c_array(), data.size() * sizeof(PodType))); +} + +template <typename PodType, std::size_t N> +inline typename detail::buffer_types<PodType>::container_type +buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes) +{ + typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type + buffer_type; + typedef typename boost::asio::detail::buffer_types<PodType>::container_type + container_type; + return container_type( + buffer_type(data.c_array(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +#else // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(boost::array<PodType, N>& data) +{ + return mutable_buffers_1( + mutable_buffer(data.c_array(), data.size() * sizeof(PodType))); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(boost::array<PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data.c_array(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(boost::array<const PodType, N>& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(boost::array<const PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +#endif // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const boost::array<PodType, N>& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const boost::array<PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +#if defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION) + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(std::array<PodType, N>& data) +{ + return mutable_buffers_1( + mutable_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new modifiable buffer that represents the given POD array. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline mutable_buffers_1 buffer(std::array<PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(std::array<const PodType, N>& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(std::array<const PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * data.size() * sizeof(PodType)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const std::array<PodType, N>& data) +{ + return const_buffers_1( + const_buffer(data.data(), data.size() * sizeof(PodType))); +} + +/// Create a new non-modifiable buffer that represents the given POD array. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + */ +template <typename PodType, std::size_t N> +inline const_buffers_1 buffer(const std::array<PodType, N>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes)); +} + +#endif // defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION) + +/// Create a new modifiable buffer that represents the given POD vector. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(PodType)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template <typename PodType, typename Allocator> +inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data) +{ + return mutable_buffers_1( + mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::vector<PodType, Allocator>::iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new modifiable buffer that represents the given POD vector. +/** + * @returns A mutable_buffers_1 value equivalent to: + * @code mutable_buffers_1( + * data.size() ? &data[0] : 0, + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template <typename PodType, typename Allocator> +inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data, + std::size_t max_size_in_bytes) +{ + return mutable_buffers_1( + mutable_buffer(data.size() ? &data[0] : 0, + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::vector<PodType, Allocator>::iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer that represents the given POD vector. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(PodType)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template <typename PodType, typename Allocator> +inline const_buffers_1 buffer( + const std::vector<PodType, Allocator>& data) +{ + return const_buffers_1( + const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::vector<PodType, Allocator>::const_iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer that represents the given POD vector. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.size() ? &data[0] : 0, + * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode + * + * @note The buffer is invalidated by any vector operation that would also + * invalidate iterators. + */ +template <typename PodType, typename Allocator> +inline const_buffers_1 buffer( + const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.size() ? &data[0] : 0, + data.size() * sizeof(PodType) < max_size_in_bytes + ? data.size() * sizeof(PodType) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::vector<PodType, Allocator>::const_iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer that represents the given string. +/** + * @returns <tt>const_buffers_1(data.data(), data.size() * sizeof(Elem))</tt>. + * + * @note The buffer is invalidated by any non-const operation called on the + * given string object. + */ +template <typename Elem, typename Traits, typename Allocator> +inline const_buffers_1 buffer( + const std::basic_string<Elem, Traits, Allocator>& data) +{ + return const_buffers_1(const_buffer(data.data(), data.size() * sizeof(Elem) +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::basic_string<Elem, Traits, Allocator>::const_iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/// Create a new non-modifiable buffer that represents the given string. +/** + * @returns A const_buffers_1 value equivalent to: + * @code const_buffers_1( + * data.data(), + * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode + * + * @note The buffer is invalidated by any non-const operation called on the + * given string object. + */ +template <typename Elem, typename Traits, typename Allocator> +inline const_buffers_1 buffer( + const std::basic_string<Elem, Traits, Allocator>& data, + std::size_t max_size_in_bytes) +{ + return const_buffers_1( + const_buffer(data.data(), + data.size() * sizeof(Elem) < max_size_in_bytes + ? data.size() * sizeof(Elem) : max_size_in_bytes +#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING) + , detail::buffer_debug_check< + typename std::basic_string<Elem, Traits, Allocator>::const_iterator + >(data.begin()) +#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING + )); +} + +/*@}*/ + +/** @defgroup buffer_copy boost::asio::buffer_copy + * + * @brief The boost::asio::buffer_copy function is used to copy bytes from a + * source buffer (or buffer sequence) to a target buffer (or buffer sequence). + * + * The @c buffer_copy function is available in two forms: + * + * @li A 2-argument form: @c buffer_copy(target, source) + * + * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy) + + * Both forms return the number of bytes actually copied. The number of bytes + * copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c If specified, @c max_bytes_to_copy. + * + * This prevents buffer overflow, regardless of the buffer sizes used in the + * copy operation. + * + * Note that @ref buffer_copy is implemented in terms of @c memcpy, and + * consequently it cannot be used to copy between overlapping memory regions. + */ +/*@{*/ + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const const_buffer& source) +{ + using namespace std; // For memcpy. + std::size_t target_size = buffer_size(target); + std::size_t source_size = buffer_size(source); + std::size_t n = target_size < source_size ? target_size : source_size; + memcpy(buffer_cast<void*>(target), buffer_cast<const void*>(source), n); + return n; +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const const_buffers_1& source) +{ + return buffer_copy(target, static_cast<const const_buffer&>(source)); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const mutable_buffer& source) +{ + return buffer_copy(target, const_buffer(source)); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const mutable_buffers_1& source) +{ + return buffer_copy(target, const_buffer(source)); +} + +/// Copies bytes from a source buffer sequence to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename ConstBufferSequence> +std::size_t buffer_copy(const mutable_buffer& target, + const ConstBufferSequence& source) +{ + std::size_t total_bytes_copied = 0; + + typename ConstBufferSequence::const_iterator source_iter = source.begin(); + typename ConstBufferSequence::const_iterator source_end = source.end(); + + for (mutable_buffer target_buffer(target); + buffer_size(target_buffer) && source_iter != source_end; ++source_iter) + { + const_buffer source_buffer(*source_iter); + std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer); + total_bytes_copied += bytes_copied; + target_buffer = target_buffer + bytes_copied; + } + + return total_bytes_copied; +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const const_buffer& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), source); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const const_buffers_1& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), + static_cast<const const_buffer&>(source)); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const mutable_buffer& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), + const_buffer(source)); +} + +/// Copies bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const mutable_buffers_1& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), + const_buffer(source)); +} + +/// Copies bytes from a source buffer sequence to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename ConstBufferSequence> +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const ConstBufferSequence& source) +{ + return buffer_copy(static_cast<const mutable_buffer&>(target), source); +} + +/// Copies bytes from a source buffer to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +std::size_t buffer_copy(const MutableBufferSequence& target, + const const_buffer& source) +{ + std::size_t total_bytes_copied = 0; + + typename MutableBufferSequence::const_iterator target_iter = target.begin(); + typename MutableBufferSequence::const_iterator target_end = target.end(); + + for (const_buffer source_buffer(source); + buffer_size(source_buffer) && target_iter != target_end; ++target_iter) + { + mutable_buffer target_buffer(*target_iter); + std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer); + total_bytes_copied += bytes_copied; + source_buffer = source_buffer + bytes_copied; + } + + return total_bytes_copied; +} + +/// Copies bytes from a source buffer to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const const_buffers_1& source) +{ + return buffer_copy(target, static_cast<const const_buffer&>(source)); +} + +/// Copies bytes from a source buffer to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const mutable_buffer& source) +{ + return buffer_copy(target, const_buffer(source)); +} + +/// Copies bytes from a source buffer to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const mutable_buffers_1& source) +{ + return buffer_copy(target, const_buffer(source)); +} + +/// Copies bytes from a source buffer sequence to a target buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence, typename ConstBufferSequence> +std::size_t buffer_copy(const MutableBufferSequence& target, + const ConstBufferSequence& source) +{ + std::size_t total_bytes_copied = 0; + + typename MutableBufferSequence::const_iterator target_iter = target.begin(); + typename MutableBufferSequence::const_iterator target_end = target.end(); + std::size_t target_buffer_offset = 0; + + typename ConstBufferSequence::const_iterator source_iter = source.begin(); + typename ConstBufferSequence::const_iterator source_end = source.end(); + std::size_t source_buffer_offset = 0; + + while (target_iter != target_end && source_iter != source_end) + { + mutable_buffer target_buffer = + mutable_buffer(*target_iter) + target_buffer_offset; + + const_buffer source_buffer = + const_buffer(*source_iter) + source_buffer_offset; + + std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer); + total_bytes_copied += bytes_copied; + + if (bytes_copied == buffer_size(target_buffer)) + { + ++target_iter; + target_buffer_offset = 0; + } + else + target_buffer_offset += bytes_copied; + + if (bytes_copied == buffer_size(source_buffer)) + { + ++source_iter; + source_buffer_offset = 0; + } + else + source_buffer_offset += bytes_copied; + } + + return total_bytes_copied; +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const const_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const const_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const mutable_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffer& target, + const mutable_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer sequence to a target +/// buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename ConstBufferSequence> +inline std::size_t buffer_copy(const mutable_buffer& target, + const ConstBufferSequence& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const const_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const const_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const mutable_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const mutable_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer sequence to a target +/// buffer. +/** + * @param target A modifiable buffer representing the memory region to which + * the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename ConstBufferSequence> +inline std::size_t buffer_copy(const mutable_buffers_1& target, + const ConstBufferSequence& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(buffer(target, max_bytes_to_copy), source); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer +/// sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const const_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(target, buffer(source, max_bytes_to_copy)); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer +/// sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer representing the memory region from + * which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const const_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(target, buffer(source, max_bytes_to_copy)); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer +/// sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const mutable_buffer& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(target, buffer(source, max_bytes_to_copy)); +} + +/// Copies a limited number of bytes from a source buffer to a target buffer +/// sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A modifiable buffer representing the memory region from which + * the bytes will be copied. The contents of the source buffer will not be + * modified. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence> +inline std::size_t buffer_copy(const MutableBufferSequence& target, + const mutable_buffers_1& source, std::size_t max_bytes_to_copy) +{ + return buffer_copy(target, buffer(source, max_bytes_to_copy)); +} + +/// Copies a limited number of bytes from a source buffer sequence to a target +/// buffer sequence. +/** + * @param target A modifiable buffer sequence representing the memory regions to + * which the bytes will be copied. + * + * @param source A non-modifiable buffer sequence representing the memory + * regions from which the bytes will be copied. + * + * @param max_bytes_to_copy The maximum number of bytes to be copied. + * + * @returns The number of bytes copied. + * + * @note The number of bytes copied is the lesser of: + * + * @li @c buffer_size(target) + * + * @li @c buffer_size(source) + * + * @li @c max_bytes_to_copy + * + * This function is implemented in terms of @c memcpy, and consequently it + * cannot be used to copy between overlapping memory regions. + */ +template <typename MutableBufferSequence, typename ConstBufferSequence> +std::size_t buffer_copy(const MutableBufferSequence& target, + const ConstBufferSequence& source, std::size_t max_bytes_to_copy) +{ + std::size_t total_bytes_copied = 0; + + typename MutableBufferSequence::const_iterator target_iter = target.begin(); + typename MutableBufferSequence::const_iterator target_end = target.end(); + std::size_t target_buffer_offset = 0; + + typename ConstBufferSequence::const_iterator source_iter = source.begin(); + typename ConstBufferSequence::const_iterator source_end = source.end(); + std::size_t source_buffer_offset = 0; + + while (total_bytes_copied != max_bytes_to_copy + && target_iter != target_end && source_iter != source_end) + { + mutable_buffer target_buffer = + mutable_buffer(*target_iter) + target_buffer_offset; + + const_buffer source_buffer = + const_buffer(*source_iter) + source_buffer_offset; + + std::size_t bytes_copied = buffer_copy(target_buffer, + source_buffer, max_bytes_to_copy - total_bytes_copied); + total_bytes_copied += bytes_copied; + + if (bytes_copied == buffer_size(target_buffer)) + { + ++target_iter; + target_buffer_offset = 0; + } + else + target_buffer_offset += bytes_copied; + + if (bytes_copied == buffer_size(source_buffer)) + { + ++source_iter; + source_buffer_offset = 0; + } + else + source_buffer_offset += bytes_copied; + } + + return total_bytes_copied; +} + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BUFFER_HPP
diff --git a/boost/boost/asio/buffered_read_stream.hpp b/boost/boost/asio/buffered_read_stream.hpp new file mode 100644 index 0000000..dea896d --- /dev/null +++ b/boost/boost/asio/buffered_read_stream.hpp
@@ -0,0 +1,246 @@ +// +// buffered_read_stream.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_READ_STREAM_HPP +#define BOOST_ASIO_BUFFERED_READ_STREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/async_result.hpp> +#include <boost/asio/buffered_read_stream_fwd.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/buffer_resize_guard.hpp> +#include <boost/asio/detail/buffered_stream_storage.hpp> +#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/io_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Adds buffering to the read-related operations of a stream. +/** + * The buffered_read_stream class template can be used to add buffering to the + * synchronous and asynchronous read operations of a stream. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template <typename Stream> +class buffered_read_stream + : private noncopyable +{ +public: + /// The type of the next layer. + typedef typename remove_reference<Stream>::type next_layer_type; + + /// The type of the lowest layer. + typedef typename next_layer_type::lowest_layer_type lowest_layer_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The default buffer size. + static const std::size_t default_buffer_size = implementation_defined; +#else + BOOST_ASIO_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024); +#endif + + /// Construct, passing the specified argument to initialise the next layer. + template <typename Arg> + explicit buffered_read_stream(Arg& a) + : next_layer_(a), + storage_(default_buffer_size) + { + } + + /// Construct, passing the specified argument to initialise the next layer. + template <typename Arg> + buffered_read_stream(Arg& a, std::size_t buffer_size) + : next_layer_(a), + storage_(buffer_size) + { + } + + /// Get a reference to the next layer. + next_layer_type& next_layer() + { + return next_layer_; + } + + /// Get a reference to the lowest layer. + lowest_layer_type& lowest_layer() + { + return next_layer_.lowest_layer(); + } + + /// Get a const reference to the lowest layer. + const lowest_layer_type& lowest_layer() const + { + return next_layer_.lowest_layer(); + } + + /// Get the io_service associated with the object. + boost::asio::io_service& get_io_service() + { + return next_layer_.get_io_service(); + } + + /// Close the stream. + void close() + { + next_layer_.close(); + } + + /// Close the stream. + boost::system::error_code close(boost::system::error_code& ec) + { + return next_layer_.close(ec); + } + + /// Write the given data to the stream. Returns the number of bytes written. + /// Throws an exception on failure. + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers) + { + return next_layer_.write_some(buffers); + } + + /// Write the given data to the stream. Returns the number of bytes written, + /// or 0 if an error occurred. + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return next_layer_.write_some(buffers, ec); + } + + /// Start an asynchronous write. The data being written must be valid for the + /// lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_write_some(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + detail::async_result_init< + WriteHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + + next_layer_.async_write_some(buffers, + BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)))(init.handler)); + + return init.result.get(); + } + + /// Fill the buffer with some data. Returns the number of bytes placed in the + /// buffer as a result of the operation. Throws an exception on failure. + std::size_t fill(); + + /// Fill the buffer with some data. Returns the number of bytes placed in the + /// buffer as a result of the operation, or 0 if an error occurred. + std::size_t fill(boost::system::error_code& ec); + + /// Start an asynchronous fill. + template <typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_fill(BOOST_ASIO_MOVE_ARG(ReadHandler) handler); + + /// Read some data from the stream. Returns the number of bytes read. Throws + /// an exception on failure. + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers); + + /// Read some data from the stream. Returns the number of bytes read or 0 if + /// an error occurred. + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec); + + /// Start an asynchronous read. The buffer into which the data will be read + /// must be valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_read_some(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler); + + /// Peek at the incoming data on the stream. Returns the number of bytes read. + /// Throws an exception on failure. + template <typename MutableBufferSequence> + std::size_t peek(const MutableBufferSequence& buffers); + + /// Peek at the incoming data on the stream. Returns the number of bytes read, + /// or 0 if an error occurred. + template <typename MutableBufferSequence> + std::size_t peek(const MutableBufferSequence& buffers, + boost::system::error_code& ec); + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail() + { + return storage_.size(); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail(boost::system::error_code& ec) + { + ec = boost::system::error_code(); + return storage_.size(); + } + +private: + /// Copy data out of the internal buffer to the specified target buffer. + /// Returns the number of bytes copied. + template <typename MutableBufferSequence> + std::size_t copy(const MutableBufferSequence& buffers) + { + std::size_t bytes_copied = boost::asio::buffer_copy( + buffers, storage_.data(), storage_.size()); + storage_.consume(bytes_copied); + return bytes_copied; + } + + /// Copy data from the internal buffer to the specified target buffer, without + /// removing the data from the internal buffer. Returns the number of bytes + /// copied. + template <typename MutableBufferSequence> + std::size_t peek_copy(const MutableBufferSequence& buffers) + { + return boost::asio::buffer_copy(buffers, storage_.data(), storage_.size()); + } + + /// The next layer. + Stream next_layer_; + + // The data in the buffer. + detail::buffered_stream_storage storage_; +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#include <boost/asio/impl/buffered_read_stream.hpp> + +#endif // BOOST_ASIO_BUFFERED_READ_STREAM_HPP
diff --git a/boost/boost/asio/buffered_read_stream_fwd.hpp b/boost/boost/asio/buffered_read_stream_fwd.hpp new file mode 100644 index 0000000..9c2a742 --- /dev/null +++ b/boost/boost/asio/buffered_read_stream_fwd.hpp
@@ -0,0 +1,27 @@ +// +// buffered_read_stream_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_READ_STREAM_FWD_HPP +#define BOOST_ASIO_BUFFERED_READ_STREAM_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +namespace boost { +namespace asio { + +template <typename Stream> +class buffered_read_stream; + +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_BUFFERED_READ_STREAM_FWD_HPP
diff --git a/boost/boost/asio/buffered_stream.hpp b/boost/boost/asio/buffered_stream.hpp new file mode 100644 index 0000000..d28620f --- /dev/null +++ b/boost/boost/asio/buffered_stream.hpp
@@ -0,0 +1,260 @@ +// +// buffered_stream.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_STREAM_HPP +#define BOOST_ASIO_BUFFERED_STREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/async_result.hpp> +#include <boost/asio/buffered_read_stream.hpp> +#include <boost/asio/buffered_write_stream.hpp> +#include <boost/asio/buffered_stream_fwd.hpp> +#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/io_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Adds buffering to the read- and write-related operations of a stream. +/** + * The buffered_stream class template can be used to add buffering to the + * synchronous and asynchronous read and write operations of a stream. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template <typename Stream> +class buffered_stream + : private noncopyable +{ +public: + /// The type of the next layer. + typedef typename remove_reference<Stream>::type next_layer_type; + + /// The type of the lowest layer. + typedef typename next_layer_type::lowest_layer_type lowest_layer_type; + + /// Construct, passing the specified argument to initialise the next layer. + template <typename Arg> + explicit buffered_stream(Arg& a) + : inner_stream_impl_(a), + stream_impl_(inner_stream_impl_) + { + } + + /// Construct, passing the specified argument to initialise the next layer. + template <typename Arg> + explicit buffered_stream(Arg& a, std::size_t read_buffer_size, + std::size_t write_buffer_size) + : inner_stream_impl_(a, write_buffer_size), + stream_impl_(inner_stream_impl_, read_buffer_size) + { + } + + /// Get a reference to the next layer. + next_layer_type& next_layer() + { + return stream_impl_.next_layer().next_layer(); + } + + /// Get a reference to the lowest layer. + lowest_layer_type& lowest_layer() + { + return stream_impl_.lowest_layer(); + } + + /// Get a const reference to the lowest layer. + const lowest_layer_type& lowest_layer() const + { + return stream_impl_.lowest_layer(); + } + + /// Get the io_service associated with the object. + boost::asio::io_service& get_io_service() + { + return stream_impl_.get_io_service(); + } + + /// Close the stream. + void close() + { + stream_impl_.close(); + } + + /// Close the stream. + boost::system::error_code close(boost::system::error_code& ec) + { + return stream_impl_.close(ec); + } + + /// Flush all data from the buffer to the next layer. Returns the number of + /// bytes written to the next layer on the last write operation. Throws an + /// exception on failure. + std::size_t flush() + { + return stream_impl_.next_layer().flush(); + } + + /// Flush all data from the buffer to the next layer. Returns the number of + /// bytes written to the next layer on the last write operation, or 0 if an + /// error occurred. + std::size_t flush(boost::system::error_code& ec) + { + return stream_impl_.next_layer().flush(ec); + } + + /// Start an asynchronous flush. + template <typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_flush(BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return stream_impl_.next_layer().async_flush( + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Write the given data to the stream. Returns the number of bytes written. + /// Throws an exception on failure. + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers) + { + return stream_impl_.write_some(buffers); + } + + /// Write the given data to the stream. Returns the number of bytes written, + /// or 0 if an error occurred. + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + return stream_impl_.write_some(buffers, ec); + } + + /// Start an asynchronous write. The data being written must be valid for the + /// lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_write_some(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + return stream_impl_.async_write_some(buffers, + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + } + + /// Fill the buffer with some data. Returns the number of bytes placed in the + /// buffer as a result of the operation. Throws an exception on failure. + std::size_t fill() + { + return stream_impl_.fill(); + } + + /// Fill the buffer with some data. Returns the number of bytes placed in the + /// buffer as a result of the operation, or 0 if an error occurred. + std::size_t fill(boost::system::error_code& ec) + { + return stream_impl_.fill(ec); + } + + /// Start an asynchronous fill. + template <typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_fill(BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + return stream_impl_.async_fill(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Read some data from the stream. Returns the number of bytes read. Throws + /// an exception on failure. + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers) + { + return stream_impl_.read_some(buffers); + } + + /// Read some data from the stream. Returns the number of bytes read or 0 if + /// an error occurred. + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return stream_impl_.read_some(buffers, ec); + } + + /// Start an asynchronous read. The buffer into which the data will be read + /// must be valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_read_some(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + return stream_impl_.async_read_some(buffers, + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read. + /// Throws an exception on failure. + template <typename MutableBufferSequence> + std::size_t peek(const MutableBufferSequence& buffers) + { + return stream_impl_.peek(buffers); + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read, + /// or 0 if an error occurred. + template <typename MutableBufferSequence> + std::size_t peek(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return stream_impl_.peek(buffers, ec); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail() + { + return stream_impl_.in_avail(); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail(boost::system::error_code& ec) + { + return stream_impl_.in_avail(ec); + } + +private: + // The buffered write stream. + typedef buffered_write_stream<Stream> write_stream_type; + write_stream_type inner_stream_impl_; + + // The buffered read stream. + typedef buffered_read_stream<write_stream_type&> read_stream_type; + read_stream_type stream_impl_; +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BUFFERED_STREAM_HPP
diff --git a/boost/boost/asio/buffered_stream_fwd.hpp b/boost/boost/asio/buffered_stream_fwd.hpp new file mode 100644 index 0000000..d3754db --- /dev/null +++ b/boost/boost/asio/buffered_stream_fwd.hpp
@@ -0,0 +1,27 @@ +// +// buffered_stream_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_STREAM_FWD_HPP +#define BOOST_ASIO_BUFFERED_STREAM_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +namespace boost { +namespace asio { + +template <typename Stream> +class buffered_stream; + +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_BUFFERED_STREAM_FWD_HPP
diff --git a/boost/boost/asio/buffered_write_stream.hpp b/boost/boost/asio/buffered_write_stream.hpp new file mode 100644 index 0000000..4b6c620 --- /dev/null +++ b/boost/boost/asio/buffered_write_stream.hpp
@@ -0,0 +1,238 @@ +// +// buffered_write_stream.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP +#define BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/buffered_write_stream_fwd.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/asio/completion_condition.hpp> +#include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/buffered_stream_storage.hpp> +#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/write.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Adds buffering to the write-related operations of a stream. +/** + * The buffered_write_stream class template can be used to add buffering to the + * synchronous and asynchronous write operations of a stream. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template <typename Stream> +class buffered_write_stream + : private noncopyable +{ +public: + /// The type of the next layer. + typedef typename remove_reference<Stream>::type next_layer_type; + + /// The type of the lowest layer. + typedef typename next_layer_type::lowest_layer_type lowest_layer_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The default buffer size. + static const std::size_t default_buffer_size = implementation_defined; +#else + BOOST_ASIO_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024); +#endif + + /// Construct, passing the specified argument to initialise the next layer. + template <typename Arg> + explicit buffered_write_stream(Arg& a) + : next_layer_(a), + storage_(default_buffer_size) + { + } + + /// Construct, passing the specified argument to initialise the next layer. + template <typename Arg> + buffered_write_stream(Arg& a, std::size_t buffer_size) + : next_layer_(a), + storage_(buffer_size) + { + } + + /// Get a reference to the next layer. + next_layer_type& next_layer() + { + return next_layer_; + } + + /// Get a reference to the lowest layer. + lowest_layer_type& lowest_layer() + { + return next_layer_.lowest_layer(); + } + + /// Get a const reference to the lowest layer. + const lowest_layer_type& lowest_layer() const + { + return next_layer_.lowest_layer(); + } + + /// Get the io_service associated with the object. + boost::asio::io_service& get_io_service() + { + return next_layer_.get_io_service(); + } + + /// Close the stream. + void close() + { + next_layer_.close(); + } + + /// Close the stream. + boost::system::error_code close(boost::system::error_code& ec) + { + return next_layer_.close(ec); + } + + /// Flush all data from the buffer to the next layer. Returns the number of + /// bytes written to the next layer on the last write operation. Throws an + /// exception on failure. + std::size_t flush(); + + /// Flush all data from the buffer to the next layer. Returns the number of + /// bytes written to the next layer on the last write operation, or 0 if an + /// error occurred. + std::size_t flush(boost::system::error_code& ec); + + /// Start an asynchronous flush. + template <typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_flush(BOOST_ASIO_MOVE_ARG(WriteHandler) handler); + + /// Write the given data to the stream. Returns the number of bytes written. + /// Throws an exception on failure. + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers); + + /// Write the given data to the stream. Returns the number of bytes written, + /// or 0 if an error occurred and the error handler did not throw. + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers, + boost::system::error_code& ec); + + /// Start an asynchronous write. The data being written must be valid for the + /// lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_write_some(const ConstBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler); + + /// Read some data from the stream. Returns the number of bytes read. Throws + /// an exception on failure. + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers) + { + return next_layer_.read_some(buffers); + } + + /// Read some data from the stream. Returns the number of bytes read or 0 if + /// an error occurred. + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return next_layer_.read_some(buffers, ec); + } + + /// Start an asynchronous read. The buffer into which the data will be read + /// must be valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_read_some(const MutableBufferSequence& buffers, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + detail::async_result_init< + ReadHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + + next_layer_.async_read_some(buffers, + BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)))(init.handler)); + + return init.result.get(); + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read. + /// Throws an exception on failure. + template <typename MutableBufferSequence> + std::size_t peek(const MutableBufferSequence& buffers) + { + return next_layer_.peek(buffers); + } + + /// Peek at the incoming data on the stream. Returns the number of bytes read, + /// or 0 if an error occurred. + template <typename MutableBufferSequence> + std::size_t peek(const MutableBufferSequence& buffers, + boost::system::error_code& ec) + { + return next_layer_.peek(buffers, ec); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail() + { + return next_layer_.in_avail(); + } + + /// Determine the amount of data that may be read without blocking. + std::size_t in_avail(boost::system::error_code& ec) + { + return next_layer_.in_avail(ec); + } + +private: + /// Copy data into the internal buffer from the specified source buffer. + /// Returns the number of bytes copied. + template <typename ConstBufferSequence> + std::size_t copy(const ConstBufferSequence& buffers); + + /// The next layer. + Stream next_layer_; + + // The data in the buffer. + detail::buffered_stream_storage storage_; +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#include <boost/asio/impl/buffered_write_stream.hpp> + +#endif // BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP
diff --git a/boost/boost/asio/buffered_write_stream_fwd.hpp b/boost/boost/asio/buffered_write_stream_fwd.hpp new file mode 100644 index 0000000..7f57107 --- /dev/null +++ b/boost/boost/asio/buffered_write_stream_fwd.hpp
@@ -0,0 +1,27 @@ +// +// buffered_write_stream_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERED_WRITE_STREAM_FWD_HPP +#define BOOST_ASIO_BUFFERED_WRITE_STREAM_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +namespace boost { +namespace asio { + +template <typename Stream> +class buffered_write_stream; + +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
diff --git a/boost/boost/asio/buffers_iterator.hpp b/boost/boost/asio/buffers_iterator.hpp new file mode 100644 index 0000000..bdf835e --- /dev/null +++ b/boost/boost/asio/buffers_iterator.hpp
@@ -0,0 +1,483 @@ +// +// buffers_iterator.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_BUFFERS_ITERATOR_HPP +#define BOOST_ASIO_BUFFERS_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <iterator> +#include <boost/asio/buffer.hpp> +#include <boost/asio/detail/assert.hpp> +#include <boost/asio/detail/type_traits.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +namespace detail +{ + template <bool IsMutable> + struct buffers_iterator_types_helper; + + template <> + struct buffers_iterator_types_helper<false> + { + typedef const_buffer buffer_type; + template <typename ByteType> + struct byte_type + { + typedef typename add_const<ByteType>::type type; + }; + }; + + template <> + struct buffers_iterator_types_helper<true> + { + typedef mutable_buffer buffer_type; + template <typename ByteType> + struct byte_type + { + typedef ByteType type; + }; + }; + + template <typename BufferSequence, typename ByteType> + struct buffers_iterator_types + { + enum + { + is_mutable = is_convertible< + typename BufferSequence::value_type, + mutable_buffer>::value + }; + typedef buffers_iterator_types_helper<is_mutable> helper; + typedef typename helper::buffer_type buffer_type; + typedef typename helper::template byte_type<ByteType>::type byte_type; + }; +} + +/// A random access iterator over the bytes in a buffer sequence. +template <typename BufferSequence, typename ByteType = char> +class buffers_iterator +{ +private: + typedef typename detail::buffers_iterator_types< + BufferSequence, ByteType>::buffer_type buffer_type; + +public: + /// The type used for the distance between two iterators. + typedef std::ptrdiff_t difference_type; + + /// The type of the value pointed to by the iterator. + typedef ByteType value_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The type of the result of applying operator->() to the iterator. + /** + * If the buffer sequence stores buffer objects that are convertible to + * mutable_buffer, this is a pointer to a non-const ByteType. Otherwise, a + * pointer to a const ByteType. + */ + typedef const_or_non_const_ByteType* pointer; +#else // defined(GENERATING_DOCUMENTATION) + typedef typename detail::buffers_iterator_types< + BufferSequence, ByteType>::byte_type* pointer; +#endif // defined(GENERATING_DOCUMENTATION) + +#if defined(GENERATING_DOCUMENTATION) + /// The type of the result of applying operator*() to the iterator. + /** + * If the buffer sequence stores buffer objects that are convertible to + * mutable_buffer, this is a reference to a non-const ByteType. Otherwise, a + * reference to a const ByteType. + */ + typedef const_or_non_const_ByteType& reference; +#else // defined(GENERATING_DOCUMENTATION) + typedef typename detail::buffers_iterator_types< + BufferSequence, ByteType>::byte_type& reference; +#endif // defined(GENERATING_DOCUMENTATION) + + /// The iterator category. + typedef std::random_access_iterator_tag iterator_category; + + /// Default constructor. Creates an iterator in an undefined state. + buffers_iterator() + : current_buffer_(), + current_buffer_position_(0), + begin_(), + current_(), + end_(), + position_(0) + { + } + + /// Construct an iterator representing the beginning of the buffers' data. + static buffers_iterator begin(const BufferSequence& buffers) +#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) + __attribute__ ((__noinline__)) +#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) + { + buffers_iterator new_iter; + new_iter.begin_ = buffers.begin(); + new_iter.current_ = buffers.begin(); + new_iter.end_ = buffers.end(); + while (new_iter.current_ != new_iter.end_) + { + new_iter.current_buffer_ = *new_iter.current_; + if (boost::asio::buffer_size(new_iter.current_buffer_) > 0) + break; + ++new_iter.current_; + } + return new_iter; + } + + /// Construct an iterator representing the end of the buffers' data. + static buffers_iterator end(const BufferSequence& buffers) +#if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) + __attribute__ ((__noinline__)) +#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) + { + buffers_iterator new_iter; + new_iter.begin_ = buffers.begin(); + new_iter.current_ = buffers.begin(); + new_iter.end_ = buffers.end(); + while (new_iter.current_ != new_iter.end_) + { + buffer_type buffer = *new_iter.current_; + new_iter.position_ += boost::asio::buffer_size(buffer); + ++new_iter.current_; + } + return new_iter; + } + + /// Dereference an iterator. + reference operator*() const + { + return dereference(); + } + + /// Dereference an iterator. + pointer operator->() const + { + return &dereference(); + } + + /// Access an individual element. + reference operator[](std::ptrdiff_t difference) const + { + buffers_iterator tmp(*this); + tmp.advance(difference); + return *tmp; + } + + /// Increment operator (prefix). + buffers_iterator& operator++() + { + increment(); + return *this; + } + + /// Increment operator (postfix). + buffers_iterator operator++(int) + { + buffers_iterator tmp(*this); + ++*this; + return tmp; + } + + /// Decrement operator (prefix). + buffers_iterator& operator--() + { + decrement(); + return *this; + } + + /// Decrement operator (postfix). + buffers_iterator operator--(int) + { + buffers_iterator tmp(*this); + --*this; + return tmp; + } + + /// Addition operator. + buffers_iterator& operator+=(std::ptrdiff_t difference) + { + advance(difference); + return *this; + } + + /// Subtraction operator. + buffers_iterator& operator-=(std::ptrdiff_t difference) + { + advance(-difference); + return *this; + } + + /// Addition operator. + friend buffers_iterator operator+(const buffers_iterator& iter, + std::ptrdiff_t difference) + { + buffers_iterator tmp(iter); + tmp.advance(difference); + return tmp; + } + + /// Addition operator. + friend buffers_iterator operator+(std::ptrdiff_t difference, + const buffers_iterator& iter) + { + buffers_iterator tmp(iter); + tmp.advance(difference); + return tmp; + } + + /// Subtraction operator. + friend buffers_iterator operator-(const buffers_iterator& iter, + std::ptrdiff_t difference) + { + buffers_iterator tmp(iter); + tmp.advance(-difference); + return tmp; + } + + /// Subtraction operator. + friend std::ptrdiff_t operator-(const buffers_iterator& a, + const buffers_iterator& b) + { + return b.distance_to(a); + } + + /// Test two iterators for equality. + friend bool operator==(const buffers_iterator& a, const buffers_iterator& b) + { + return a.equal(b); + } + + /// Test two iterators for inequality. + friend bool operator!=(const buffers_iterator& a, const buffers_iterator& b) + { + return !a.equal(b); + } + + /// Compare two iterators. + friend bool operator<(const buffers_iterator& a, const buffers_iterator& b) + { + return a.distance_to(b) > 0; + } + + /// Compare two iterators. + friend bool operator<=(const buffers_iterator& a, const buffers_iterator& b) + { + return !(b < a); + } + + /// Compare two iterators. + friend bool operator>(const buffers_iterator& a, const buffers_iterator& b) + { + return b < a; + } + + /// Compare two iterators. + friend bool operator>=(const buffers_iterator& a, const buffers_iterator& b) + { + return !(a < b); + } + +private: + // Dereference the iterator. + reference dereference() const + { + return buffer_cast<pointer>(current_buffer_)[current_buffer_position_]; + } + + // Compare two iterators for equality. + bool equal(const buffers_iterator& other) const + { + return position_ == other.position_; + } + + // Increment the iterator. + void increment() + { + BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds"); + ++position_; + + // Check if the increment can be satisfied by the current buffer. + ++current_buffer_position_; + if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_)) + return; + + // Find the next non-empty buffer. + ++current_; + current_buffer_position_ = 0; + while (current_ != end_) + { + current_buffer_ = *current_; + if (boost::asio::buffer_size(current_buffer_) > 0) + return; + ++current_; + } + } + + // Decrement the iterator. + void decrement() + { + BOOST_ASIO_ASSERT(position_ > 0 && "iterator out of bounds"); + --position_; + + // Check if the decrement can be satisfied by the current buffer. + if (current_buffer_position_ != 0) + { + --current_buffer_position_; + return; + } + + // Find the previous non-empty buffer. + typename BufferSequence::const_iterator iter = current_; + while (iter != begin_) + { + --iter; + buffer_type buffer = *iter; + std::size_t buffer_size = boost::asio::buffer_size(buffer); + if (buffer_size > 0) + { + current_ = iter; + current_buffer_ = buffer; + current_buffer_position_ = buffer_size - 1; + return; + } + } + } + + // Advance the iterator by the specified distance. + void advance(std::ptrdiff_t n) + { + if (n > 0) + { + BOOST_ASIO_ASSERT(current_ != end_ && "iterator out of bounds"); + for (;;) + { + std::ptrdiff_t current_buffer_balance + = boost::asio::buffer_size(current_buffer_) + - current_buffer_position_; + + // Check if the advance can be satisfied by the current buffer. + if (current_buffer_balance > n) + { + position_ += n; + current_buffer_position_ += n; + return; + } + + // Update position. + n -= current_buffer_balance; + position_ += current_buffer_balance; + + // Move to next buffer. If it is empty then it will be skipped on the + // next iteration of this loop. + if (++current_ == end_) + { + BOOST_ASIO_ASSERT(n == 0 && "iterator out of bounds"); + current_buffer_ = buffer_type(); + current_buffer_position_ = 0; + return; + } + current_buffer_ = *current_; + current_buffer_position_ = 0; + } + } + else if (n < 0) + { + std::size_t abs_n = -n; + BOOST_ASIO_ASSERT(position_ >= abs_n && "iterator out of bounds"); + for (;;) + { + // Check if the advance can be satisfied by the current buffer. + if (current_buffer_position_ >= abs_n) + { + position_ -= abs_n; + current_buffer_position_ -= abs_n; + return; + } + + // Update position. + abs_n -= current_buffer_position_; + position_ -= current_buffer_position_; + + // Check if we've reached the beginning of the buffers. + if (current_ == begin_) + { + BOOST_ASIO_ASSERT(abs_n == 0 && "iterator out of bounds"); + current_buffer_position_ = 0; + return; + } + + // Find the previous non-empty buffer. + typename BufferSequence::const_iterator iter = current_; + while (iter != begin_) + { + --iter; + buffer_type buffer = *iter; + std::size_t buffer_size = boost::asio::buffer_size(buffer); + if (buffer_size > 0) + { + current_ = iter; + current_buffer_ = buffer; + current_buffer_position_ = buffer_size; + break; + } + } + } + } + } + + // Determine the distance between two iterators. + std::ptrdiff_t distance_to(const buffers_iterator& other) const + { + return other.position_ - position_; + } + + buffer_type current_buffer_; + std::size_t current_buffer_position_; + typename BufferSequence::const_iterator begin_; + typename BufferSequence::const_iterator current_; + typename BufferSequence::const_iterator end_; + std::size_t position_; +}; + +/// Construct an iterator representing the beginning of the buffers' data. +template <typename BufferSequence> +inline buffers_iterator<BufferSequence> buffers_begin( + const BufferSequence& buffers) +{ + return buffers_iterator<BufferSequence>::begin(buffers); +} + +/// Construct an iterator representing the end of the buffers' data. +template <typename BufferSequence> +inline buffers_iterator<BufferSequence> buffers_end( + const BufferSequence& buffers) +{ + return buffers_iterator<BufferSequence>::end(buffers); +} + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_BUFFERS_ITERATOR_HPP
diff --git a/boost/boost/asio/completion_condition.hpp b/boost/boost/asio/completion_condition.hpp new file mode 100644 index 0000000..58c7d95 --- /dev/null +++ b/boost/boost/asio/completion_condition.hpp
@@ -0,0 +1,220 @@ +// +// completion_condition.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_COMPLETION_CONDITION_HPP +#define BOOST_ASIO_COMPLETION_CONDITION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +namespace detail { + +// The default maximum number of bytes to transfer in a single operation. +enum default_max_transfer_size_t { default_max_transfer_size = 65536 }; + +// Adapt result of old-style completion conditions (which had a bool result +// where true indicated that the operation was complete). +inline std::size_t adapt_completion_condition_result(bool result) +{ + return result ? 0 : default_max_transfer_size; +} + +// Adapt result of current completion conditions (which have a size_t result +// where 0 means the operation is complete, and otherwise the result is the +// maximum number of bytes to transfer on the next underlying operation). +inline std::size_t adapt_completion_condition_result(std::size_t result) +{ + return result; +} + +class transfer_all_t +{ +public: + typedef std::size_t result_type; + + template <typename Error> + std::size_t operator()(const Error& err, std::size_t) + { + return !!err ? 0 : default_max_transfer_size; + } +}; + +class transfer_at_least_t +{ +public: + typedef std::size_t result_type; + + explicit transfer_at_least_t(std::size_t minimum) + : minimum_(minimum) + { + } + + template <typename Error> + std::size_t operator()(const Error& err, std::size_t bytes_transferred) + { + return (!!err || bytes_transferred >= minimum_) + ? 0 : default_max_transfer_size; + } + +private: + std::size_t minimum_; +}; + +class transfer_exactly_t +{ +public: + typedef std::size_t result_type; + + explicit transfer_exactly_t(std::size_t size) + : size_(size) + { + } + + template <typename Error> + std::size_t operator()(const Error& err, std::size_t bytes_transferred) + { + return (!!err || bytes_transferred >= size_) ? 0 : + (size_ - bytes_transferred < default_max_transfer_size + ? size_ - bytes_transferred : std::size_t(default_max_transfer_size)); + } + +private: + std::size_t size_; +}; + +} // namespace detail + +/** + * @defgroup completion_condition Completion Condition Function Objects + * + * Function objects used for determining when a read or write operation should + * complete. + */ +/*@{*/ + +/// Return a completion condition function object that indicates that a read or +/// write operation should continue until all of the data has been transferred, +/// or until an error occurs. +/** + * This function is used to create an object, of unspecified type, that meets + * CompletionCondition requirements. + * + * @par Example + * Reading until a buffer is full: + * @code + * boost::array<char, 128> buf; + * boost::system::error_code ec; + * std::size_t n = boost::asio::read( + * sock, boost::asio::buffer(buf), + * boost::asio::transfer_all(), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * // n == 128 + * } + * @endcode + */ +#if defined(GENERATING_DOCUMENTATION) +unspecified transfer_all(); +#else +inline detail::transfer_all_t transfer_all() +{ + return detail::transfer_all_t(); +} +#endif + +/// Return a completion condition function object that indicates that a read or +/// write operation should continue until a minimum number of bytes has been +/// transferred, or until an error occurs. +/** + * This function is used to create an object, of unspecified type, that meets + * CompletionCondition requirements. + * + * @par Example + * Reading until a buffer is full or contains at least 64 bytes: + * @code + * boost::array<char, 128> buf; + * boost::system::error_code ec; + * std::size_t n = boost::asio::read( + * sock, boost::asio::buffer(buf), + * boost::asio::transfer_at_least(64), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * // n >= 64 && n <= 128 + * } + * @endcode + */ +#if defined(GENERATING_DOCUMENTATION) +unspecified transfer_at_least(std::size_t minimum); +#else +inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum) +{ + return detail::transfer_at_least_t(minimum); +} +#endif + +/// Return a completion condition function object that indicates that a read or +/// write operation should continue until an exact number of bytes has been +/// transferred, or until an error occurs. +/** + * This function is used to create an object, of unspecified type, that meets + * CompletionCondition requirements. + * + * @par Example + * Reading until a buffer is full or contains exactly 64 bytes: + * @code + * boost::array<char, 128> buf; + * boost::system::error_code ec; + * std::size_t n = boost::asio::read( + * sock, boost::asio::buffer(buf), + * boost::asio::transfer_exactly(64), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * // n == 64 + * } + * @endcode + */ +#if defined(GENERATING_DOCUMENTATION) +unspecified transfer_exactly(std::size_t size); +#else +inline detail::transfer_exactly_t transfer_exactly(std::size_t size) +{ + return detail::transfer_exactly_t(size); +} +#endif + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_COMPLETION_CONDITION_HPP
diff --git a/boost/boost/asio/connect.hpp b/boost/boost/asio/connect.hpp new file mode 100644 index 0000000..8557cc0 --- /dev/null +++ b/boost/boost/asio/connect.hpp
@@ -0,0 +1,825 @@ +// +// connect.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_CONNECT_HPP +#define BOOST_ASIO_CONNECT_HPP + +#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/async_result.hpp> +#include <boost/asio/basic_socket.hpp> +#include <boost/asio/error.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/** + * @defgroup connect boost::asio::connect + * + * @brief Establishes a socket connection by trying each endpoint in a sequence. + */ +/*@{*/ + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @throws boost::system::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is boost::asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * boost::asio::connect(s, r.resolve(q)); @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to boost::asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * boost::system::error_code ec; + * boost::asio::connect(s, r.resolve(q), ec); + * if (ec) + * { + * // An error occurred. + * } @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, boost::system::error_code& ec); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @throws boost::system::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is boost::asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::socket s(io_service); + * boost::asio::connect(s, i, end); @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to boost::asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::socket s(io_service); + * boost::system::error_code ec; + * boost::asio::connect(s, i, end, ec); + * if (ec) + * { + * // An error occurred. + * } @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, boost::system::error_code& ec); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const boost::system::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @throws boost::system::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is boost::asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const boost::system::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the boost::asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * tcp::resolver::iterator i = boost::asio::connect( + * s, r.resolve(q), my_connect_condition()); + * std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, ConnectCondition connect_condition); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const boost::system::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to boost::asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const boost::system::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the boost::asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * boost::system::error_code ec; + * tcp::resolver::iterator i = boost::asio::connect( + * s, r.resolve(q), my_connect_condition(), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * std::cout << "Connected to: " << i->endpoint() << std::endl; + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin, + ConnectCondition connect_condition, boost::system::error_code& ec); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const boost::system::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @throws boost::system::system_error Thrown on failure. If the sequence is + * empty, the associated @c error_code is boost::asio::error::not_found. + * Otherwise, contains the error from the last connection attempt. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const boost::system::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the boost::asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::socket s(io_service); + * i = boost::asio::connect(s, i, end, my_connect_condition()); + * std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin, + Iterator end, ConnectCondition connect_condition); + +/// Establishes a socket connection by trying each endpoint in a sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c connect member + * function, once for each endpoint in the sequence, until a connection is + * successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const boost::system::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @param ec Set to indicate what error occurred, if any. If the sequence is + * empty, set to boost::asio::error::not_found. Otherwise, contains the error + * from the last connection attempt. + * + * @returns On success, an iterator denoting the successfully connected + * endpoint. Otherwise, the end iterator. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const boost::system::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the boost::asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::resolver::iterator i = r.resolve(q), end; + * tcp::socket s(io_service); + * boost::system::error_code ec; + * i = boost::asio::connect(s, i, end, my_connect_condition(), ec); + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * std::cout << "Connected to: " << i->endpoint() << std::endl; + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ConnectCondition> +Iterator connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, ConnectCondition connect_condition, + boost::system::error_code& ec); + +/*@}*/ + +/** + * @defgroup async_connect boost::asio::async_connect + * + * @brief Asynchronously establishes a socket connection by trying each + * endpoint in a sequence. + */ +/*@{*/ + +/// Asynchronously establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // boost::asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const boost::system::error_code& error, + * + * // On success, an iterator denoting the successfully + * // connected endpoint. Otherwise, the end iterator. + * Iterator iterator + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * + * // ... + * + * r.async_resolve(q, resolve_handler); + * + * // ... + * + * void resolve_handler( + * const boost::system::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (!ec) + * { + * boost::asio::async_connect(s, i, connect_handler); + * } + * } + * + * // ... + * + * void connect_handler( + * const boost::system::error_code& ec, + * tcp::resolver::iterator i) + * { + * // ... + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ComposedConnectHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (boost::system::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler); + +/// Asynchronously establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // boost::asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const boost::system::error_code& error, + * + * // On success, an iterator denoting the successfully + * // connected endpoint. Otherwise, the end iterator. + * Iterator iterator + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * + * // ... + * + * r.async_resolve(q, resolve_handler); + * + * // ... + * + * void resolve_handler( + * const boost::system::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (!ec) + * { + * tcp::resolver::iterator end; + * boost::asio::async_connect(s, i, end, connect_handler); + * } + * } + * + * // ... + * + * void connect_handler( + * const boost::system::error_code& ec, + * tcp::resolver::iterator i) + * { + * // ... + * } @endcode + */ +template <typename Protocol, typename SocketService, + typename Iterator, typename ComposedConnectHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (boost::system::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, + BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler); + +/// Asynchronously establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const boost::system::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // boost::asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const boost::system::error_code& error, + * + * // On success, an iterator denoting the successfully + * // connected endpoint. Otherwise, the end iterator. + * Iterator iterator + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @note This overload assumes that a default constructed object of type @c + * Iterator represents the end of the sequence. This is a valid assumption for + * iterator types such as @c boost::asio::ip::tcp::resolver::iterator. + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const boost::system::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the boost::asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * + * // ... + * + * r.async_resolve(q, resolve_handler); + * + * // ... + * + * void resolve_handler( + * const boost::system::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (!ec) + * { + * boost::asio::async_connect(s, i, + * my_connect_condition(), + * connect_handler); + * } + * } + * + * // ... + * + * void connect_handler( + * const boost::system::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * std::cout << "Connected to: " << i->endpoint() << std::endl; + * } + * } @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (boost::system::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin, + ConnectCondition connect_condition, + BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler); + +/// Asynchronously establishes a socket connection by trying each endpoint in a +/// sequence. +/** + * This function attempts to connect a socket to one of a sequence of + * endpoints. It does this by repeated calls to the socket's @c async_connect + * member function, once for each endpoint in the sequence, until a connection + * is successfully established. + * + * @param s The socket to be connected. If the socket is already open, it will + * be closed. + * + * @param begin An iterator pointing to the start of a sequence of endpoints. + * + * @param end An iterator pointing to the end of a sequence of endpoints. + * + * @param connect_condition A function object that is called prior to each + * connection attempt. The signature of the function object must be: + * @code Iterator connect_condition( + * const boost::system::error_code& ec, + * Iterator next); @endcode + * The @c ec parameter contains the result from the most recent connect + * operation. Before the first connection attempt, @c ec is always set to + * indicate success. The @c next parameter is an iterator pointing to the next + * endpoint to be tried. The function object should return the next iterator, + * but is permitted to return a different iterator so that endpoints may be + * skipped. The implementation guarantees that the function object will never + * be called with the end iterator. + * + * @param handler The handler to be called when the connect operation + * completes. Copies will be made of the handler as required. The function + * signature of the handler must be: + * @code void handler( + * // Result of operation. if the sequence is empty, set to + * // boost::asio::error::not_found. Otherwise, contains the + * // error from the last connection attempt. + * const boost::system::error_code& error, + * + * // On success, an iterator denoting the successfully + * // connected endpoint. Otherwise, the end iterator. + * Iterator iterator + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the handler will not be invoked from within this function. Invocation + * of the handler will be performed in a manner equivalent to using + * boost::asio::io_service::post(). + * + * @par Example + * The following connect condition function object can be used to output + * information about the individual connection attempts: + * @code struct my_connect_condition + * { + * template <typename Iterator> + * Iterator operator()( + * const boost::system::error_code& ec, + * Iterator next) + * { + * if (ec) std::cout << "Error: " << ec.message() << std::endl; + * std::cout << "Trying: " << next->endpoint() << std::endl; + * return next; + * } + * }; @endcode + * It would be used with the boost::asio::connect function as follows: + * @code tcp::resolver r(io_service); + * tcp::resolver::query q("host", "service"); + * tcp::socket s(io_service); + * + * // ... + * + * r.async_resolve(q, resolve_handler); + * + * // ... + * + * void resolve_handler( + * const boost::system::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (!ec) + * { + * tcp::resolver::iterator end; + * boost::asio::async_connect(s, i, end, + * my_connect_condition(), + * connect_handler); + * } + * } + * + * // ... + * + * void connect_handler( + * const boost::system::error_code& ec, + * tcp::resolver::iterator i) + * { + * if (ec) + * { + * // An error occurred. + * } + * else + * { + * std::cout << "Connected to: " << i->endpoint() << std::endl; + * } + * } @endcode + */ +template <typename Protocol, typename SocketService, typename Iterator, + typename ConnectCondition, typename ComposedConnectHandler> +BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler, + void (boost::system::error_code, Iterator)) +async_connect(basic_socket<Protocol, SocketService>& s, + Iterator begin, Iterator end, ConnectCondition connect_condition, + BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler); + +/*@}*/ + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#include <boost/asio/impl/connect.hpp> + +#endif
diff --git a/boost/boost/asio/coroutine.hpp b/boost/boost/asio/coroutine.hpp new file mode 100644 index 0000000..cc760ad --- /dev/null +++ b/boost/boost/asio/coroutine.hpp
@@ -0,0 +1,330 @@ +// +// coroutine.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_COROUTINE_HPP +#define BOOST_ASIO_COROUTINE_HPP + +namespace boost { +namespace asio { +namespace detail { + +class coroutine_ref; + +} // namespace detail + +/// Provides support for implementing stackless coroutines. +/** + * The @c coroutine class may be used to implement stackless coroutines. The + * class itself is used to store the current state of the coroutine. + * + * Coroutines are copy-constructible and assignable, and the space overhead is + * a single int. They can be used as a base class: + * + * @code class session : coroutine + * { + * ... + * }; @endcode + * + * or as a data member: + * + * @code class session + * { + * ... + * coroutine coro_; + * }; @endcode + * + * or even bound in as a function argument using lambdas or @c bind(). The + * important thing is that as the application maintains a copy of the object + * for as long as the coroutine must be kept alive. + * + * @par Pseudo-keywords + * + * A coroutine is used in conjunction with certain "pseudo-keywords", which + * are implemented as macros. These macros are defined by a header file: + * + * @code #include <boost/asio/yield.hpp>@endcode + * + * and may conversely be undefined as follows: + * + * @code #include <boost/asio/unyield.hpp>@endcode + * + * <b>reenter</b> + * + * The @c reenter macro is used to define the body of a coroutine. It takes a + * single argument: a pointer or reference to a coroutine object. For example, + * if the base class is a coroutine object you may write: + * + * @code reenter (this) + * { + * ... coroutine body ... + * } @endcode + * + * and if a data member or other variable you can write: + * + * @code reenter (coro_) + * { + * ... coroutine body ... + * } @endcode + * + * When @c reenter is executed at runtime, control jumps to the location of the + * last @c yield or @c fork. + * + * The coroutine body may also be a single statement, such as: + * + * @code reenter (this) for (;;) + * { + * ... + * } @endcode + * + * @b Limitation: The @c reenter macro is implemented using a switch. This + * means that you must take care when using local variables within the + * coroutine body. The local variable is not allowed in a position where + * reentering the coroutine could bypass the variable definition. + * + * <b>yield <em>statement</em></b> + * + * This form of the @c yield keyword is often used with asynchronous operations: + * + * @code yield socket_->async_read_some(buffer(*buffer_), *this); @endcode + * + * This divides into four logical steps: + * + * @li @c yield saves the current state of the coroutine. + * @li The statement initiates the asynchronous operation. + * @li The resume point is defined immediately following the statement. + * @li Control is transferred to the end of the coroutine body. + * + * When the asynchronous operation completes, the function object is invoked + * and @c reenter causes control to transfer to the resume point. It is + * important to remember to carry the coroutine state forward with the + * asynchronous operation. In the above snippet, the current class is a + * function object object with a coroutine object as base class or data member. + * + * The statement may also be a compound statement, and this permits us to + * define local variables with limited scope: + * + * @code yield + * { + * mutable_buffers_1 b = buffer(*buffer_); + * socket_->async_read_some(b, *this); + * } @endcode + * + * <b>yield return <em>expression</em> ;</b> + * + * This form of @c yield is often used in generators or coroutine-based parsers. + * For example, the function object: + * + * @code struct interleave : coroutine + * { + * istream& is1; + * istream& is2; + * char operator()(char c) + * { + * reenter (this) for (;;) + * { + * yield return is1.get(); + * yield return is2.get(); + * } + * } + * }; @endcode + * + * defines a trivial coroutine that interleaves the characters from two input + * streams. + * + * This type of @c yield divides into three logical steps: + * + * @li @c yield saves the current state of the coroutine. + * @li The resume point is defined immediately following the semicolon. + * @li The value of the expression is returned from the function. + * + * <b>yield ;</b> + * + * This form of @c yield is equivalent to the following steps: + * + * @li @c yield saves the current state of the coroutine. + * @li The resume point is defined immediately following the semicolon. + * @li Control is transferred to the end of the coroutine body. + * + * This form might be applied when coroutines are used for cooperative + * threading and scheduling is explicitly managed. For example: + * + * @code struct task : coroutine + * { + * ... + * void operator()() + * { + * reenter (this) + * { + * while (... not finished ...) + * { + * ... do something ... + * yield; + * ... do some more ... + * yield; + * } + * } + * } + * ... + * }; + * ... + * task t1, t2; + * for (;;) + * { + * t1(); + * t2(); + * } @endcode + * + * <b>yield break ;</b> + * + * The final form of @c yield is used to explicitly terminate the coroutine. + * This form is comprised of two steps: + * + * @li @c yield sets the coroutine state to indicate termination. + * @li Control is transferred to the end of the coroutine body. + * + * Once terminated, calls to is_complete() return true and the coroutine cannot + * be reentered. + * + * Note that a coroutine may also be implicitly terminated if the coroutine + * body is exited without a yield, e.g. by return, throw or by running to the + * end of the body. + * + * <b>fork <em>statement</em></b> + * + * The @c fork pseudo-keyword is used when "forking" a coroutine, i.e. splitting + * it into two (or more) copies. One use of @c fork is in a server, where a new + * coroutine is created to handle each client connection: + * + * @code reenter (this) + * { + * do + * { + * socket_.reset(new tcp::socket(io_service_)); + * yield acceptor->async_accept(*socket_, *this); + * fork server(*this)(); + * } while (is_parent()); + * ... client-specific handling follows ... + * } @endcode + * + * The logical steps involved in a @c fork are: + * + * @li @c fork saves the current state of the coroutine. + * @li The statement creates a copy of the coroutine and either executes it + * immediately or schedules it for later execution. + * @li The resume point is defined immediately following the semicolon. + * @li For the "parent", control immediately continues from the next line. + * + * The functions is_parent() and is_child() can be used to differentiate + * between parent and child. You would use these functions to alter subsequent + * control flow. + * + * Note that @c fork doesn't do the actual forking by itself. It is the + * application's responsibility to create a clone of the coroutine and call it. + * The clone can be called immediately, as above, or scheduled for delayed + * execution using something like io_service::post(). + * + * @par Alternate macro names + * + * If preferred, an application can use macro names that follow a more typical + * naming convention, rather than the pseudo-keywords. These are: + * + * @li @c BOOST_ASIO_CORO_REENTER instead of @c reenter + * @li @c BOOST_ASIO_CORO_YIELD instead of @c yield + * @li @c BOOST_ASIO_CORO_FORK instead of @c fork + */ +class coroutine +{ +public: + /// Constructs a coroutine in its initial state. + coroutine() : value_(0) {} + + /// Returns true if the coroutine is the child of a fork. + bool is_child() const { return value_ < 0; } + + /// Returns true if the coroutine is the parent of a fork. + bool is_parent() const { return !is_child(); } + + /// Returns true if the coroutine has reached its terminal state. + bool is_complete() const { return value_ == -1; } + +private: + friend class detail::coroutine_ref; + int value_; +}; + + +namespace detail { + +class coroutine_ref +{ +public: + coroutine_ref(coroutine& c) : value_(c.value_), modified_(false) {} + coroutine_ref(coroutine* c) : value_(c->value_), modified_(false) {} + ~coroutine_ref() { if (!modified_) value_ = -1; } + operator int() const { return value_; } + int& operator=(int v) { modified_ = true; return value_ = v; } +private: + void operator=(const coroutine_ref&); + int& value_; + bool modified_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#define BOOST_ASIO_CORO_REENTER(c) \ + switch (::boost::asio::detail::coroutine_ref _coro_value = c) \ + case -1: if (_coro_value) \ + { \ + goto terminate_coroutine; \ + terminate_coroutine: \ + _coro_value = -1; \ + goto bail_out_of_coroutine; \ + bail_out_of_coroutine: \ + break; \ + } \ + else case 0: + +#define BOOST_ASIO_CORO_YIELD_IMPL(n) \ + for (_coro_value = (n);;) \ + if (_coro_value == 0) \ + { \ + case (n): ; \ + break; \ + } \ + else \ + switch (_coro_value ? 0 : 1) \ + for (;;) \ + case -1: if (_coro_value) \ + goto terminate_coroutine; \ + else for (;;) \ + case 1: if (_coro_value) \ + goto bail_out_of_coroutine; \ + else case 0: + +#define BOOST_ASIO_CORO_FORK_IMPL(n) \ + for (_coro_value = -(n);; _coro_value = (n)) \ + if (_coro_value == (n)) \ + { \ + case -(n): ; \ + break; \ + } \ + else + +#if defined(_MSC_VER) +# define BOOST_ASIO_CORO_YIELD BOOST_ASIO_CORO_YIELD_IMPL(__COUNTER__ + 1) +# define BOOST_ASIO_CORO_FORK BOOST_ASIO_CORO_FORK_IMPL(__COUNTER__ + 1) +#else // defined(_MSC_VER) +# define BOOST_ASIO_CORO_YIELD BOOST_ASIO_CORO_YIELD_IMPL(__LINE__) +# define BOOST_ASIO_CORO_FORK BOOST_ASIO_CORO_FORK_IMPL(__LINE__) +#endif // defined(_MSC_VER) + +#endif // BOOST_ASIO_COROUTINE_HPP
diff --git a/boost/boost/asio/datagram_socket_service.hpp b/boost/boost/asio/datagram_socket_service.hpp new file mode 100644 index 0000000..3c7bb08 --- /dev/null +++ b/boost/boost/asio/datagram_socket_service.hpp
@@ -0,0 +1,434 @@ +// +// datagram_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP +#define BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/async_result.hpp> +#include <boost/asio/detail/type_traits.hpp> +#include <boost/asio/error.hpp> +#include <boost/asio/io_service.hpp> + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include <boost/asio/detail/null_socket_service.hpp> +#elif defined(BOOST_ASIO_HAS_IOCP) +# include <boost/asio/detail/win_iocp_socket_service.hpp> +#else +# include <boost/asio/detail/reactive_socket_service.hpp> +#endif + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Default service implementation for a datagram socket. +template <typename Protocol> +class datagram_socket_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base<datagram_socket_service<Protocol> > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The protocol type. + typedef Protocol protocol_type; + + /// The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + +private: + // The type of the platform-specific implementation. +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + typedef detail::null_socket_service<Protocol> service_impl_type; +#elif defined(BOOST_ASIO_HAS_IOCP) + typedef detail::win_iocp_socket_service<Protocol> service_impl_type; +#else + typedef detail::reactive_socket_service<Protocol> service_impl_type; +#endif + +public: + /// The type of a datagram socket. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// (Deprecated: Use native_handle_type.) The native socket type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_type; +#else + typedef typename service_impl_type::native_handle_type native_type; +#endif + + /// The native socket type. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef typename service_impl_type::native_handle_type native_handle_type; +#endif + + /// Construct a new datagram socket service for the specified io_service. + explicit datagram_socket_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + datagram_socket_service<Protocol> >(io_service), + service_impl_(io_service) + { + } + + /// Construct a new datagram socket implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + +#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + /// Move-construct a new datagram socket implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) + { + service_impl_.move_construct(impl, other_impl); + } + + /// Move-assign from another datagram socket implementation. + void move_assign(implementation_type& impl, + datagram_socket_service& other_service, + implementation_type& other_impl) + { + service_impl_.move_assign(impl, other_service.service_impl_, other_impl); + } + + /// Move-construct a new datagram socket implementation from another protocol + /// type. + template <typename Protocol1> + void converting_move_construct(implementation_type& impl, + typename datagram_socket_service< + Protocol1>::implementation_type& other_impl, + typename enable_if<is_convertible< + Protocol1, Protocol>::value>::type* = 0) + { + service_impl_.template converting_move_construct<Protocol1>( + impl, other_impl); + } +#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Destroy a datagram socket implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + // Open a new datagram socket implementation. + boost::system::error_code open(implementation_type& impl, + const protocol_type& protocol, boost::system::error_code& ec) + { + if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_DGRAM)) + service_impl_.open(impl, protocol, ec); + else + ec = boost::asio::error::invalid_argument; + return ec; + } + + /// Assign an existing native socket to a datagram socket. + boost::system::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_handle_type& native_socket, + boost::system::error_code& ec) + { + return service_impl_.assign(impl, protocol, native_socket, ec); + } + + /// Determine whether the socket is open. + bool is_open(const implementation_type& impl) const + { + return service_impl_.is_open(impl); + } + + /// Close a datagram socket implementation. + boost::system::error_code close(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.close(impl, ec); + } + + /// (Deprecated: Use native_handle().) Get the native socket implementation. + native_type native(implementation_type& impl) + { + return service_impl_.native_handle(impl); + } + + /// Get the native socket implementation. + native_handle_type native_handle(implementation_type& impl) + { + return service_impl_.native_handle(impl); + } + + /// Cancel all asynchronous operations associated with the socket. + boost::system::error_code cancel(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Determine whether the socket is at the out-of-band data mark. + bool at_mark(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.at_mark(impl, ec); + } + + /// Determine the number of bytes available for reading. + std::size_t available(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.available(impl, ec); + } + + // Bind the datagram socket to the specified local endpoint. + boost::system::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, boost::system::error_code& ec) + { + return service_impl_.bind(impl, endpoint, ec); + } + + /// Connect the datagram socket to the specified endpoint. + boost::system::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, boost::system::error_code& ec) + { + return service_impl_.connect(impl, peer_endpoint, ec); + } + + /// Start an asynchronous connect. + template <typename ConnectHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler, + void (boost::system::error_code)) + async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, + BOOST_ASIO_MOVE_ARG(ConnectHandler) handler) + { + detail::async_result_init< + ConnectHandler, void (boost::system::error_code)> init( + BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler)); + + service_impl_.async_connect(impl, peer_endpoint, init.handler); + + return init.result.get(); + } + + /// Set a socket option. + template <typename SettableSocketOption> + boost::system::error_code set_option(implementation_type& impl, + const SettableSocketOption& option, boost::system::error_code& ec) + { + return service_impl_.set_option(impl, option, ec); + } + + /// Get a socket option. + template <typename GettableSocketOption> + boost::system::error_code get_option(const implementation_type& impl, + GettableSocketOption& option, boost::system::error_code& ec) const + { + return service_impl_.get_option(impl, option, ec); + } + + /// Perform an IO control command on the socket. + template <typename IoControlCommand> + boost::system::error_code io_control(implementation_type& impl, + IoControlCommand& command, boost::system::error_code& ec) + { + return service_impl_.io_control(impl, command, ec); + } + + /// Gets the non-blocking mode of the socket. + bool non_blocking(const implementation_type& impl) const + { + return service_impl_.non_blocking(impl); + } + + /// Sets the non-blocking mode of the socket. + boost::system::error_code non_blocking(implementation_type& impl, + bool mode, boost::system::error_code& ec) + { + return service_impl_.non_blocking(impl, mode, ec); + } + + /// Gets the non-blocking mode of the native socket implementation. + bool native_non_blocking(const implementation_type& impl) const + { + return service_impl_.native_non_blocking(impl); + } + + /// Sets the non-blocking mode of the native socket implementation. + boost::system::error_code native_non_blocking(implementation_type& impl, + bool mode, boost::system::error_code& ec) + { + return service_impl_.native_non_blocking(impl, mode, ec); + } + + /// Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.local_endpoint(impl, ec); + } + + /// Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + boost::system::error_code& ec) const + { + return service_impl_.remote_endpoint(impl, ec); + } + + /// Disable sends or receives on the socket. + boost::system::error_code shutdown(implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + return service_impl_.shutdown(impl, what, ec); + } + + /// Send the given data to the peer. + template <typename ConstBufferSequence> + std::size_t send(implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.send(impl, buffers, flags, ec); + } + + /// Start an asynchronous send. + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send(implementation_type& impl, const ConstBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + detail::async_result_init< + WriteHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + + service_impl_.async_send(impl, buffers, flags, init.handler); + + return init.result.get(); + } + + /// Send a datagram to the specified endpoint. + template <typename ConstBufferSequence> + std::size_t send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.send_to(impl, buffers, destination, flags, ec); + } + + /// Start an asynchronous send. + template <typename ConstBufferSequence, typename WriteHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, + void (boost::system::error_code, std::size_t)) + async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, const endpoint_type& destination, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(WriteHandler) handler) + { + detail::async_result_init< + WriteHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(WriteHandler)(handler)); + + service_impl_.async_send_to(impl, buffers, + destination, flags, init.handler); + + return init.result.get(); + } + + /// Receive some data from the peer. + template <typename MutableBufferSequence> + std::size_t receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.receive(impl, buffers, flags, ec); + } + + /// Start an asynchronous receive. + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive(implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + detail::async_result_init< + ReadHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + + service_impl_.async_receive(impl, buffers, flags, init.handler); + + return init.result.get(); + } + + /// Receive a datagram with the endpoint of the sender. + template <typename MutableBufferSequence> + std::size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, boost::system::error_code& ec) + { + return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, + ec); + } + + /// Start an asynchronous receive that will get the endpoint of the sender. + template <typename MutableBufferSequence, typename ReadHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, + void (boost::system::error_code, std::size_t)) + async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, + BOOST_ASIO_MOVE_ARG(ReadHandler) handler) + { + detail::async_result_init< + ReadHandler, void (boost::system::error_code, std::size_t)> init( + BOOST_ASIO_MOVE_CAST(ReadHandler)(handler)); + + service_impl_.async_receive_from(impl, buffers, + sender_endpoint, flags, init.handler); + + return init.result.get(); + } + +private: + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + service_impl_.shutdown_service(); + } + + // The platform-specific implementation. + service_impl_type service_impl_; +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP
diff --git a/boost/boost/asio/deadline_timer.hpp b/boost/boost/asio/deadline_timer.hpp new file mode 100644 index 0000000..91bc2fb --- /dev/null +++ b/boost/boost/asio/deadline_timer.hpp
@@ -0,0 +1,40 @@ +// +// deadline_timer.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DEADLINE_TIMER_HPP +#define BOOST_ASIO_DEADLINE_TIMER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ + || defined(GENERATING_DOCUMENTATION) + +#include <boost/asio/detail/socket_types.hpp> // Must come before posix_time. +#include <boost/asio/basic_deadline_timer.hpp> + +#include <boost/date_time/posix_time/posix_time_types.hpp> + +namespace boost { +namespace asio { + +/// Typedef for the typical usage of timer. Uses a UTC clock. +typedef basic_deadline_timer<boost::posix_time::ptime> deadline_timer; + +} // namespace asio +} // namespace boost + +#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) + // || defined(GENERATING_DOCUMENTATION) + +#endif // BOOST_ASIO_DEADLINE_TIMER_HPP
diff --git a/boost/boost/asio/deadline_timer_service.hpp b/boost/boost/asio/deadline_timer_service.hpp new file mode 100644 index 0000000..142d625 --- /dev/null +++ b/boost/boost/asio/deadline_timer_service.hpp
@@ -0,0 +1,173 @@ +// +// deadline_timer_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP +#define BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \ + || defined(GENERATING_DOCUMENTATION) + +#include <cstddef> +#include <boost/asio/async_result.hpp> +#include <boost/asio/detail/deadline_timer_service.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/time_traits.hpp> +#include <boost/asio/detail/timer_queue_ptime.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { + +/// Default service implementation for a timer. +template <typename TimeType, + typename TimeTraits = boost::asio::time_traits<TimeType> > +class deadline_timer_service +#if defined(GENERATING_DOCUMENTATION) + : public boost::asio::io_service::service +#else + : public boost::asio::detail::service_base< + deadline_timer_service<TimeType, TimeTraits> > +#endif +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// The unique service identifier. + static boost::asio::io_service::id id; +#endif + + /// The time traits type. + typedef TimeTraits traits_type; + + /// The time type. + typedef typename traits_type::time_type time_type; + + /// The duration type. + typedef typename traits_type::duration_type duration_type; + +private: + // The type of the platform-specific implementation. + typedef detail::deadline_timer_service<traits_type> service_impl_type; + +public: + /// The implementation type of the deadline timer. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined implementation_type; +#else + typedef typename service_impl_type::implementation_type implementation_type; +#endif + + /// Construct a new timer service for the specified io_service. + explicit deadline_timer_service(boost::asio::io_service& io_service) + : boost::asio::detail::service_base< + deadline_timer_service<TimeType, TimeTraits> >(io_service), + service_impl_(io_service) + { + } + + /// Construct a new timer implementation. + void construct(implementation_type& impl) + { + service_impl_.construct(impl); + } + + /// Destroy a timer implementation. + void destroy(implementation_type& impl) + { + service_impl_.destroy(impl); + } + + /// Cancel any asynchronous wait operations associated with the timer. + std::size_t cancel(implementation_type& impl, boost::system::error_code& ec) + { + return service_impl_.cancel(impl, ec); + } + + /// Cancels one asynchronous wait operation associated with the timer. + std::size_t cancel_one(implementation_type& impl, + boost::system::error_code& ec) + { + return service_impl_.cancel_one(impl, ec); + } + + /// Get the expiry time for the timer as an absolute time. + time_type expires_at(const implementation_type& impl) const + { + return service_impl_.expires_at(impl); + } + + /// Set the expiry time for the timer as an absolute time. + std::size_t expires_at(implementation_type& impl, + const time_type& expiry_time, boost::system::error_code& ec) + { + return service_impl_.expires_at(impl, expiry_time, ec); + } + + /// Get the expiry time for the timer relative to now. + duration_type expires_from_now(const implementation_type& impl) const + { + return service_impl_.expires_from_now(impl); + } + + /// Set the expiry time for the timer relative to now. + std::size_t expires_from_now(implementation_type& impl, + const duration_type& expiry_time, boost::system::error_code& ec) + { + return service_impl_.expires_from_now(impl, expiry_time, ec); + } + + // Perform a blocking wait on the timer. + void wait(implementation_type& impl, boost::system::error_code& ec) + { + service_impl_.wait(impl, ec); + } + + // Start an asynchronous wait on the timer. + template <typename WaitHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler, + void (boost::system::error_code)) + async_wait(implementation_type& impl, + BOOST_ASIO_MOVE_ARG(WaitHandler) handler) + { + detail::async_result_init< + WaitHandler, void (boost::system::error_code)> init( + BOOST_ASIO_MOVE_CAST(WaitHandler)(handler)); + + service_impl_.async_wait(impl, init.handler); + + return init.result.get(); + } + +private: + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + service_impl_.shutdown_service(); + } + + // The platform-specific implementation. + service_impl_type service_impl_; +}; + +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) + // || defined(GENERATING_DOCUMENTATION) + +#endif // BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP
diff --git a/boost/boost/asio/detail/addressof.hpp b/boost/boost/asio/detail/addressof.hpp new file mode 100644 index 0000000..2791c56 --- /dev/null +++ b/boost/boost/asio/detail/addressof.hpp
@@ -0,0 +1,40 @@ +// +// detail/addressof.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_ADDRESSOF_HPP +#define BOOST_ASIO_DETAIL_ADDRESSOF_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_STD_ADDRESSOF) +# include <memory> +#else // defined(BOOST_ASIO_HAS_STD_ADDRESSOF) +# include <boost/utility/addressof.hpp> +#endif // defined(BOOST_ASIO_HAS_STD_ADDRESSOF) + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_HAS_STD_ADDRESSOF) +using std::addressof; +#else // defined(BOOST_ASIO_HAS_STD_ADDRESSOF) +using boost::addressof; +#endif // defined(BOOST_ASIO_HAS_STD_ADDRESSOF) + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_ADDRESSOF_HPP
diff --git a/boost/boost/asio/detail/array.hpp b/boost/boost/asio/detail/array.hpp new file mode 100644 index 0000000..5a58413 --- /dev/null +++ b/boost/boost/asio/detail/array.hpp
@@ -0,0 +1,40 @@ +// +// detail/array.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_ARRAY_HPP +#define BOOST_ASIO_DETAIL_ARRAY_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_STD_ARRAY) +# include <array> +#else // defined(BOOST_ASIO_HAS_STD_ARRAY) +# include <boost/array.hpp> +#endif // defined(BOOST_ASIO_HAS_STD_ARRAY) + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_HAS_STD_ARRAY) +using std::array; +#else // defined(BOOST_ASIO_HAS_STD_ARRAY) +using boost::array; +#endif // defined(BOOST_ASIO_HAS_STD_ARRAY) + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_ARRAY_HPP
diff --git a/boost/boost/asio/detail/array_fwd.hpp b/boost/boost/asio/detail/array_fwd.hpp new file mode 100644 index 0000000..7f6c612 --- /dev/null +++ b/boost/boost/asio/detail/array_fwd.hpp
@@ -0,0 +1,34 @@ +// +// detail/array_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_ARRAY_FWD_HPP +#define BOOST_ASIO_DETAIL_ARRAY_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +namespace boost { + +template<class T, std::size_t N> +class array; + +} // namespace boost + +// Standard library components can't be forward declared, so we'll have to +// include the array header. Fortunately, it's fairly lightweight and doesn't +// add significantly to the compile time. +#if defined(BOOST_ASIO_HAS_STD_ARRAY) +# include <array> +#endif // defined(BOOST_ASIO_HAS_STD_ARRAY) + +#endif // BOOST_ASIO_DETAIL_ARRAY_FWD_HPP
diff --git a/boost/boost/asio/detail/assert.hpp b/boost/boost/asio/detail/assert.hpp new file mode 100644 index 0000000..8847ea1 --- /dev/null +++ b/boost/boost/asio/detail/assert.hpp
@@ -0,0 +1,32 @@ +// +// detail/assert.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_ASSERT_HPP +#define BOOST_ASIO_DETAIL_ASSERT_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_BOOST_ASSERT) +# include <boost/assert.hpp> +#else // defined(BOOST_ASIO_HAS_BOOST_ASSERT) +# include <cassert> +#endif // defined(BOOST_ASIO_HAS_BOOST_ASSERT) + +#if defined(BOOST_ASIO_HAS_BOOST_ASSERT) +# define BOOST_ASIO_ASSERT(expr) BOOST_ASSERT(expr) +#else // defined(BOOST_ASIO_HAS_BOOST_ASSERT) +# define BOOST_ASIO_ASSERT(expr) assert(expr) +#endif // defined(BOOST_ASIO_HAS_BOOST_ASSERT) + +#endif // BOOST_ASIO_DETAIL_ASSERT_HPP
diff --git a/boost/boost/asio/detail/atomic_count.hpp b/boost/boost/asio/detail/atomic_count.hpp new file mode 100644 index 0000000..ce0ef73 --- /dev/null +++ b/boost/boost/asio/detail/atomic_count.hpp
@@ -0,0 +1,47 @@ +// +// detail/atomic_count.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_ATOMIC_COUNT_HPP +#define BOOST_ASIO_DETAIL_ATOMIC_COUNT_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_THREADS) +// Nothing to include. +#elif defined(BOOST_ASIO_HAS_STD_ATOMIC) +# include <atomic> +#else // defined(BOOST_ASIO_HAS_STD_ATOMIC) +# include <boost/detail/atomic_count.hpp> +#endif // defined(BOOST_ASIO_HAS_STD_ATOMIC) + +namespace boost { +namespace asio { +namespace detail { + +#if !defined(BOOST_ASIO_HAS_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 +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_ATOMIC_COUNT_HPP
diff --git a/boost/boost/asio/detail/base_from_completion_cond.hpp b/boost/boost/asio/detail/base_from_completion_cond.hpp new file mode 100644 index 0000000..3570899 --- /dev/null +++ b/boost/boost/asio/detail/base_from_completion_cond.hpp
@@ -0,0 +1,70 @@ +// +// detail/base_from_completion_cond.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_BASE_FROM_COMPLETION_COND_HPP +#define BOOST_ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP + +#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/completion_condition.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename CompletionCondition> +class base_from_completion_cond +{ +protected: + explicit base_from_completion_cond(CompletionCondition completion_condition) + : completion_condition_(completion_condition) + { + } + + std::size_t check_for_completion( + const boost::system::error_code& ec, + std::size_t total_transferred) + { + return detail::adapt_completion_condition_result( + completion_condition_(ec, total_transferred)); + } + +private: + CompletionCondition completion_condition_; +}; + +template <> +class base_from_completion_cond<transfer_all_t> +{ +protected: + explicit base_from_completion_cond(transfer_all_t) + { + } + + static std::size_t check_for_completion( + const boost::system::error_code& ec, + std::size_t total_transferred) + { + return transfer_all_t()(ec, total_transferred); + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP
diff --git a/boost/boost/asio/detail/bind_handler.hpp b/boost/boost/asio/detail/bind_handler.hpp new file mode 100644 index 0000000..9219910 --- /dev/null +++ b/boost/boost/asio/detail/bind_handler.hpp
@@ -0,0 +1,491 @@ +// +// detail/bind_handler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_BIND_HANDLER_HPP +#define BOOST_ASIO_DETAIL_BIND_HANDLER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/handler_alloc_helpers.hpp> +#include <boost/asio/detail/handler_cont_helpers.hpp> +#include <boost/asio/detail/handler_invoke_helpers.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Handler, typename Arg1> +class binder1 +{ +public: + binder1(const Handler& handler, const Arg1& arg1) + : handler_(handler), + arg1_(arg1) + { + } + + binder1(Handler& handler, const Arg1& arg1) + : handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_)); + } + + void operator()() const + { + handler_(arg1_); + } + +//private: + Handler handler_; + Arg1 arg1_; +}; + +template <typename Handler, typename Arg1> +inline void* asio_handler_allocate(std::size_t size, + binder1<Handler, Arg1>* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder1<Handler, Arg1>* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1> +inline bool asio_handler_is_continuation( + binder1<Handler, Arg1>* this_handler) +{ + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1> +inline void asio_handler_invoke(Function& function, + binder1<Handler, Arg1>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1> +inline void asio_handler_invoke(const Function& function, + binder1<Handler, Arg1>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1> +inline binder1<Handler, Arg1> bind_handler(Handler handler, + const Arg1& arg1) +{ + return binder1<Handler, Arg1>(handler, arg1); +} + +template <typename Handler, typename Arg1, typename Arg2> +class binder2 +{ +public: + binder2(const Handler& handler, const Arg1& arg1, const Arg2& arg2) + : handler_(handler), + arg1_(arg1), + arg2_(arg2) + { + } + + binder2(Handler& handler, const Arg1& arg1, const Arg2& arg2) + : handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1), + arg2_(arg2) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_), + static_cast<const Arg2&>(arg2_)); + } + + void operator()() const + { + handler_(arg1_, arg2_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; +}; + +template <typename Handler, typename Arg1, typename Arg2> +inline void* asio_handler_allocate(std::size_t size, + binder2<Handler, Arg1, Arg2>* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder2<Handler, Arg1, Arg2>* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2> +inline bool asio_handler_is_continuation( + binder2<Handler, Arg1, Arg2>* this_handler) +{ + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2> +inline void asio_handler_invoke(Function& function, + binder2<Handler, Arg1, Arg2>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2> +inline void asio_handler_invoke(const Function& function, + binder2<Handler, Arg1, Arg2>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2> +inline binder2<Handler, Arg1, Arg2> bind_handler(Handler handler, + const Arg1& arg1, const Arg2& arg2) +{ + return binder2<Handler, Arg1, Arg2>(handler, arg1, arg2); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +class binder3 +{ +public: + binder3(const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3) + : handler_(handler), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3) + { + } + + binder3(Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3) + : handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_), + static_cast<const Arg2&>(arg2_), + static_cast<const Arg3&>(arg3_)); + } + + void operator()() const + { + handler_(arg1_, arg2_, arg3_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; + Arg3 arg3_; +}; + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +inline void* asio_handler_allocate(std::size_t size, + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +inline bool asio_handler_is_continuation( + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3> +inline void asio_handler_invoke(Function& function, + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3> +inline void asio_handler_invoke(const Function& function, + binder3<Handler, Arg1, Arg2, Arg3>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3> +inline binder3<Handler, Arg1, Arg2, Arg3> bind_handler(Handler handler, + const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) +{ + return binder3<Handler, Arg1, Arg2, Arg3>(handler, arg1, arg2, arg3); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +class binder4 +{ +public: + binder4(const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) + : handler_(handler), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4) + { + } + + binder4(Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) + : handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_), + static_cast<const Arg2&>(arg2_), + static_cast<const Arg3&>(arg3_), + static_cast<const Arg4&>(arg4_)); + } + + void operator()() const + { + handler_(arg1_, arg2_, arg3_, arg4_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; + Arg3 arg3_; + Arg4 arg4_; +}; + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +inline void* asio_handler_allocate(std::size_t size, + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +inline bool asio_handler_is_continuation( + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3, typename Arg4> +inline void asio_handler_invoke(Function& function, + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3, typename Arg4> +inline void asio_handler_invoke(const Function& function, + binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4> +inline binder4<Handler, Arg1, Arg2, Arg3, Arg4> bind_handler( + Handler handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) +{ + return binder4<Handler, Arg1, Arg2, Arg3, Arg4>(handler, arg1, arg2, arg3, + arg4); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +class binder5 +{ +public: + binder5(const Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) + : handler_(handler), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4), + arg5_(arg5) + { + } + + binder5(Handler& handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) + : handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), + arg1_(arg1), + arg2_(arg2), + arg3_(arg3), + arg4_(arg4), + arg5_(arg5) + { + } + + void operator()() + { + handler_(static_cast<const Arg1&>(arg1_), + static_cast<const Arg2&>(arg2_), + static_cast<const Arg3&>(arg3_), + static_cast<const Arg4&>(arg4_), + static_cast<const Arg5&>(arg5_)); + } + + void operator()() const + { + handler_(arg1_, arg2_, arg3_, arg4_, arg5_); + } + +//private: + Handler handler_; + Arg1 arg1_; + Arg2 arg2_; + Arg3 arg3_; + Arg4 arg4_; + Arg5 arg5_; +}; + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +inline void* asio_handler_allocate(std::size_t size, + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + return boost_asio_handler_alloc_helpers::allocate( + size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +inline void asio_handler_deallocate(void* pointer, std::size_t size, + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + boost_asio_handler_alloc_helpers::deallocate( + pointer, size, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +inline bool asio_handler_is_continuation( + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + return boost_asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3, typename Arg4, typename Arg5> +inline void asio_handler_invoke(Function& function, + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Function, typename Handler, typename Arg1, typename Arg2, + typename Arg3, typename Arg4, typename Arg5> +inline void asio_handler_invoke(const Function& function, + binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) +{ + boost_asio_handler_invoke_helpers::invoke( + function, this_handler->handler_); +} + +template <typename Handler, typename Arg1, typename Arg2, typename Arg3, + typename Arg4, typename Arg5> +inline binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5> bind_handler( + Handler handler, const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) +{ + return binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>(handler, arg1, arg2, + arg3, arg4, arg5); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_BIND_HANDLER_HPP
diff --git a/boost/boost/asio/detail/buffer_resize_guard.hpp b/boost/boost/asio/detail/buffer_resize_guard.hpp new file mode 100644 index 0000000..8bb0e73 --- /dev/null +++ b/boost/boost/asio/detail/buffer_resize_guard.hpp
@@ -0,0 +1,68 @@ +// +// detail/buffer_resize_guard.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP +#define BOOST_ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/limits.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// Helper class to manage buffer resizing in an exception safe way. +template <typename Buffer> +class buffer_resize_guard +{ +public: + // Constructor. + buffer_resize_guard(Buffer& buffer) + : buffer_(buffer), + old_size_(buffer.size()) + { + } + + // Destructor rolls back the buffer resize unless commit was called. + ~buffer_resize_guard() + { + if (old_size_ != (std::numeric_limits<size_t>::max)()) + { + buffer_.resize(old_size_); + } + } + + // Commit the resize transaction. + void commit() + { + old_size_ = (std::numeric_limits<size_t>::max)(); + } + +private: + // The buffer being managed. + Buffer& buffer_; + + // The size of the buffer at the time the guard was constructed. + size_t old_size_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP
diff --git a/boost/boost/asio/detail/buffer_sequence_adapter.hpp b/boost/boost/asio/detail/buffer_sequence_adapter.hpp new file mode 100644 index 0000000..8cf8980 --- /dev/null +++ b/boost/boost/asio/detail/buffer_sequence_adapter.hpp
@@ -0,0 +1,385 @@ +// +// detail/buffer_sequence_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP +#define BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP + +#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/buffer.hpp> +#include <boost/asio/detail/array_fwd.hpp> +#include <boost/asio/detail/socket_types.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class buffer_sequence_adapter_base +{ +protected: +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 1 }; + + typedef Windows::Storage::Streams::IBuffer^ native_buffer_type; + + BOOST_ASIO_DECL static void init_native_buffer( + native_buffer_type& buf, + const boost::asio::mutable_buffer& buffer); + + BOOST_ASIO_DECL static void init_native_buffer( + native_buffer_type& buf, + const boost::asio::const_buffer& buffer); +#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + + typedef WSABUF native_buffer_type; + + static void init_native_buffer(WSABUF& buf, + const boost::asio::mutable_buffer& buffer) + { + buf.buf = boost::asio::buffer_cast<char*>(buffer); + buf.len = static_cast<ULONG>(boost::asio::buffer_size(buffer)); + } + + static void init_native_buffer(WSABUF& buf, + const boost::asio::const_buffer& buffer) + { + buf.buf = const_cast<char*>(boost::asio::buffer_cast<const char*>(buffer)); + buf.len = static_cast<ULONG>(boost::asio::buffer_size(buffer)); + } +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // The maximum number of buffers to support in a single operation. + enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; + + typedef iovec native_buffer_type; + + static void init_iov_base(void*& base, void* addr) + { + base = addr; + } + + template <typename T> + static void init_iov_base(T& base, void* addr) + { + base = static_cast<T>(addr); + } + + static void init_native_buffer(iovec& iov, + const boost::asio::mutable_buffer& buffer) + { + init_iov_base(iov.iov_base, boost::asio::buffer_cast<void*>(buffer)); + iov.iov_len = boost::asio::buffer_size(buffer); + } + + static void init_native_buffer(iovec& iov, + const boost::asio::const_buffer& buffer) + { + init_iov_base(iov.iov_base, const_cast<void*>( + boost::asio::buffer_cast<const void*>(buffer))); + iov.iov_len = boost::asio::buffer_size(buffer); + } +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +}; + +// Helper class to translate buffers into the native buffer representation. +template <typename Buffer, typename Buffers> +class buffer_sequence_adapter + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter(const Buffers& buffer_sequence) + : count_(0), total_buffer_size_(0) + { + typename Buffers::const_iterator iter = buffer_sequence.begin(); + typename Buffers::const_iterator end = buffer_sequence.end(); + for (; iter != end && count_ < max_buffers; ++iter, ++count_) + { + Buffer buffer(*iter); + init_native_buffer(buffers_[count_], buffer); + total_buffer_size_ += boost::asio::buffer_size(buffer); + } + } + + native_buffer_type* buffers() + { + return buffers_; + } + + std::size_t count() const + { + return count_; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const Buffers& buffer_sequence) + { + typename Buffers::const_iterator iter = buffer_sequence.begin(); + typename Buffers::const_iterator end = buffer_sequence.end(); + std::size_t i = 0; + for (; iter != end && i < max_buffers; ++iter, ++i) + if (boost::asio::buffer_size(Buffer(*iter)) > 0) + return false; + return true; + } + + static void validate(const Buffers& buffer_sequence) + { + typename Buffers::const_iterator iter = buffer_sequence.begin(); + typename Buffers::const_iterator end = buffer_sequence.end(); + for (; iter != end; ++iter) + { + Buffer buffer(*iter); + boost::asio::buffer_cast<const void*>(buffer); + } + } + + static Buffer first(const Buffers& buffer_sequence) + { + typename Buffers::const_iterator iter = buffer_sequence.begin(); + typename Buffers::const_iterator end = buffer_sequence.end(); + for (; iter != end; ++iter) + { + Buffer buffer(*iter); + if (boost::asio::buffer_size(buffer) != 0) + return buffer; + } + return Buffer(); + } + +private: + native_buffer_type buffers_[max_buffers]; + std::size_t count_; + std::size_t total_buffer_size_; +}; + +template <typename Buffer> +class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1> + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter( + const boost::asio::mutable_buffers_1& buffer_sequence) + { + init_native_buffer(buffer_, Buffer(buffer_sequence)); + total_buffer_size_ = boost::asio::buffer_size(buffer_sequence); + } + + native_buffer_type* buffers() + { + return &buffer_; + } + + std::size_t count() const + { + return 1; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const boost::asio::mutable_buffers_1& buffer_sequence) + { + return boost::asio::buffer_size(buffer_sequence) == 0; + } + + static void validate(const boost::asio::mutable_buffers_1& buffer_sequence) + { + boost::asio::buffer_cast<const void*>(buffer_sequence); + } + + static Buffer first(const boost::asio::mutable_buffers_1& buffer_sequence) + { + return Buffer(buffer_sequence); + } + +private: + native_buffer_type buffer_; + std::size_t total_buffer_size_; +}; + +template <typename Buffer> +class buffer_sequence_adapter<Buffer, boost::asio::const_buffers_1> + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter( + const boost::asio::const_buffers_1& buffer_sequence) + { + init_native_buffer(buffer_, Buffer(buffer_sequence)); + total_buffer_size_ = boost::asio::buffer_size(buffer_sequence); + } + + native_buffer_type* buffers() + { + return &buffer_; + } + + std::size_t count() const + { + return 1; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const boost::asio::const_buffers_1& buffer_sequence) + { + return boost::asio::buffer_size(buffer_sequence) == 0; + } + + static void validate(const boost::asio::const_buffers_1& buffer_sequence) + { + boost::asio::buffer_cast<const void*>(buffer_sequence); + } + + static Buffer first(const boost::asio::const_buffers_1& buffer_sequence) + { + return Buffer(buffer_sequence); + } + +private: + native_buffer_type buffer_; + std::size_t total_buffer_size_; +}; + +template <typename Buffer, typename Elem> +class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> > + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter( + const boost::array<Elem, 2>& buffer_sequence) + { + init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); + init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); + total_buffer_size_ = boost::asio::buffer_size(buffer_sequence[0]) + + boost::asio::buffer_size(buffer_sequence[1]); + } + + native_buffer_type* buffers() + { + return buffers_; + } + + std::size_t count() const + { + return 2; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const boost::array<Elem, 2>& buffer_sequence) + { + return boost::asio::buffer_size(buffer_sequence[0]) == 0 + && boost::asio::buffer_size(buffer_sequence[1]) == 0; + } + + static void validate(const boost::array<Elem, 2>& buffer_sequence) + { + boost::asio::buffer_cast<const void*>(buffer_sequence[0]); + boost::asio::buffer_cast<const void*>(buffer_sequence[1]); + } + + static Buffer first(const boost::array<Elem, 2>& buffer_sequence) + { + return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0 + ? buffer_sequence[0] : buffer_sequence[1]); + } + +private: + native_buffer_type buffers_[2]; + std::size_t total_buffer_size_; +}; + +#if defined(BOOST_ASIO_HAS_STD_ARRAY) + +template <typename Buffer, typename Elem> +class buffer_sequence_adapter<Buffer, std::array<Elem, 2> > + : buffer_sequence_adapter_base +{ +public: + explicit buffer_sequence_adapter( + const std::array<Elem, 2>& buffer_sequence) + { + init_native_buffer(buffers_[0], Buffer(buffer_sequence[0])); + init_native_buffer(buffers_[1], Buffer(buffer_sequence[1])); + total_buffer_size_ = boost::asio::buffer_size(buffer_sequence[0]) + + boost::asio::buffer_size(buffer_sequence[1]); + } + + native_buffer_type* buffers() + { + return buffers_; + } + + std::size_t count() const + { + return 2; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty(const std::array<Elem, 2>& buffer_sequence) + { + return boost::asio::buffer_size(buffer_sequence[0]) == 0 + && boost::asio::buffer_size(buffer_sequence[1]) == 0; + } + + static void validate(const std::array<Elem, 2>& buffer_sequence) + { + boost::asio::buffer_cast<const void*>(buffer_sequence[0]); + boost::asio::buffer_cast<const void*>(buffer_sequence[1]); + } + + static Buffer first(const std::array<Elem, 2>& buffer_sequence) + { + return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0 + ? buffer_sequence[0] : buffer_sequence[1]); + } + +private: + native_buffer_type buffers_[2]; + std::size_t total_buffer_size_; +}; + +#endif // defined(BOOST_ASIO_HAS_STD_ARRAY) + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include <boost/asio/detail/impl/buffer_sequence_adapter.ipp> +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // BOOST_ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP
diff --git a/boost/boost/asio/detail/buffered_stream_storage.hpp b/boost/boost/asio/detail/buffered_stream_storage.hpp new file mode 100644 index 0000000..f4fc5cc --- /dev/null +++ b/boost/boost/asio/detail/buffered_stream_storage.hpp
@@ -0,0 +1,128 @@ +// +// detail/buffered_stream_storage.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP +#define BOOST_ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/asio/detail/assert.hpp> +#include <cstddef> +#include <cstring> +#include <vector> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class buffered_stream_storage +{ +public: + // The type of the bytes stored in the buffer. + typedef unsigned char byte_type; + + // The type used for offsets into the buffer. + typedef std::size_t size_type; + + // Constructor. + explicit buffered_stream_storage(std::size_t buffer_capacity) + : begin_offset_(0), + end_offset_(0), + buffer_(buffer_capacity) + { + } + + /// Clear the buffer. + void clear() + { + begin_offset_ = 0; + end_offset_ = 0; + } + + // Return a pointer to the beginning of the unread data. + mutable_buffer data() + { + return boost::asio::buffer(buffer_) + begin_offset_; + } + + // Return a pointer to the beginning of the unread data. + const_buffer data() const + { + return boost::asio::buffer(buffer_) + begin_offset_; + } + + // Is there no unread data in the buffer. + bool empty() const + { + return begin_offset_ == end_offset_; + } + + // Return the amount of unread data the is in the buffer. + size_type size() const + { + return end_offset_ - begin_offset_; + } + + // Resize the buffer to the specified length. + void resize(size_type length) + { + BOOST_ASIO_ASSERT(length <= capacity()); + if (begin_offset_ + length <= capacity()) + { + end_offset_ = begin_offset_ + length; + } + else + { + using namespace std; // For memmove. + memmove(&buffer_[0], &buffer_[0] + begin_offset_, size()); + end_offset_ = length; + begin_offset_ = 0; + } + } + + // Return the maximum size for data in the buffer. + size_type capacity() const + { + return buffer_.size(); + } + + // Consume multiple bytes from the beginning of the buffer. + void consume(size_type count) + { + BOOST_ASIO_ASSERT(begin_offset_ + count <= end_offset_); + begin_offset_ += count; + if (empty()) + clear(); + } + +private: + // The offset to the beginning of the unread data. + size_type begin_offset_; + + // The offset to the end of the unread data. + size_type end_offset_; + + // The data in the buffer. + std::vector<byte_type> buffer_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP
diff --git a/boost/boost/asio/detail/call_stack.hpp b/boost/boost/asio/detail/call_stack.hpp new file mode 100644 index 0000000..65f7122 --- /dev/null +++ b/boost/boost/asio/detail/call_stack.hpp
@@ -0,0 +1,127 @@ +// +// detail/call_stack.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_CALL_STACK_HPP +#define BOOST_ASIO_DETAIL_CALL_STACK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/tss_ptr.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// Helper class to determine whether or not the current thread is inside an +// invocation of io_service::run() for a specified io_service object. +template <typename Key, typename Value = unsigned char> +class call_stack +{ +public: + // Context class automatically pushes the key/value pair on to the stack. + class context + : private noncopyable + { + public: + // Push the key on to the stack. + explicit context(Key* k) + : key_(k), + next_(call_stack<Key, Value>::top_) + { + value_ = reinterpret_cast<unsigned char*>(this); + call_stack<Key, Value>::top_ = this; + } + + // Push the key/value pair on to the stack. + context(Key* k, Value& v) + : key_(k), + value_(&v), + next_(call_stack<Key, Value>::top_) + { + call_stack<Key, Value>::top_ = this; + } + + // Pop the key/value pair from the stack. + ~context() + { + call_stack<Key, Value>::top_ = next_; + } + + // Find the next context with the same key. + Value* next_by_key() const + { + context* elem = next_; + while (elem) + { + if (elem->key_ == key_) + return elem->value_; + elem = elem->next_; + } + return 0; + } + + private: + friend class call_stack<Key, Value>; + + // The key associated with the context. + Key* key_; + + // The value associated with the context. + Value* value_; + + // The next element in the stack. + context* next_; + }; + + friend class context; + + // Determine whether the specified owner is on the stack. Returns address of + // key if present, 0 otherwise. + static Value* contains(Key* k) + { + context* elem = top_; + while (elem) + { + if (elem->key_ == k) + return elem->value_; + elem = elem->next_; + } + 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_; +}; + +template <typename Key, typename Value> +tss_ptr<typename call_stack<Key, Value>::context> +call_stack<Key, Value>::top_; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_CALL_STACK_HPP
diff --git a/boost/boost/asio/detail/chrono_time_traits.hpp b/boost/boost/asio/detail/chrono_time_traits.hpp new file mode 100644 index 0000000..c0e073b --- /dev/null +++ b/boost/boost/asio/detail/chrono_time_traits.hpp
@@ -0,0 +1,192 @@ +// +// detail/chrono_time_traits.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_CHRONO_TIME_TRAITS_HPP +#define BOOST_ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/cstdint.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// Helper template to compute the greatest common divisor. +template <int64_t v1, int64_t v2> +struct gcd { enum { value = gcd<v2, v1 % v2>::value }; }; + +template <int64_t v1> +struct gcd<v1, 0> { enum { value = v1 }; }; + +// Adapts std::chrono clocks for use with a deadline timer. +template <typename Clock, typename WaitTraits> +struct chrono_time_traits +{ + // The clock type. + typedef Clock clock_type; + + // The duration type of the clock. + typedef typename clock_type::duration duration_type; + + // The time point type of the clock. + typedef typename clock_type::time_point time_type; + + // The period of the clock. + typedef typename duration_type::period period_type; + + // Get the current time. + static time_type now() + { + return clock_type::now(); + } + + // Add a duration to a time. + static time_type add(const time_type& t, const duration_type& d) + { + const time_type epoch; + if (t >= epoch) + { + if ((time_type::max)() - t < d) + return (time_type::max)(); + } + else // t < epoch + { + if (-(t - (time_type::min)()) > d) + return (time_type::min)(); + } + + return t + d; + } + + // Subtract one time from another. + static duration_type subtract(const time_type& t1, const time_type& t2) + { + const time_type epoch; + if (t1 >= epoch) + { + if (t2 >= epoch) + { + return t1 - t2; + } + else if (t2 == (time_type::min)()) + { + return (duration_type::max)(); + } + else if ((time_type::max)() - t1 < epoch - t2) + { + return (duration_type::max)(); + } + else + { + return t1 - t2; + } + } + else // t1 < epoch + { + if (t2 < epoch) + { + return t1 - t2; + } + else if (t1 == (time_type::min)()) + { + return (duration_type::min)(); + } + else if ((time_type::max)() - t2 < epoch - t1) + { + return (duration_type::min)(); + } + else + { + return -(t2 - t1); + } + } + } + + // Test whether one time is less than another. + static bool less_than(const time_type& t1, const time_type& t2) + { + return t1 < t2; + } + + // Implement just enough of the posix_time::time_duration interface to supply + // what the timer_queue requires. + class posix_time_duration + { + public: + explicit posix_time_duration(const duration_type& d) + : d_(d) + { + } + + int64_t ticks() const + { + return d_.count(); + } + + int64_t total_seconds() const + { + return duration_cast<1, 1>(); + } + + int64_t total_milliseconds() const + { + return duration_cast<1, 1000>(); + } + + int64_t total_microseconds() const + { + return duration_cast<1, 1000000>(); + } + + private: + template <int64_t Num, int64_t Den> + int64_t duration_cast() const + { + const int64_t num1 = period_type::num / gcd<period_type::num, Num>::value; + const int64_t num2 = Num / gcd<period_type::num, Num>::value; + + const int64_t den1 = period_type::den / gcd<period_type::den, Den>::value; + const int64_t den2 = Den / gcd<period_type::den, Den>::value; + + const int64_t num = num1 * den2; + const int64_t den = num2 * den1; + + if (num == 1 && den == 1) + return ticks(); + else if (num != 1 && den == 1) + return ticks() * num; + else if (num == 1 && period_type::den != 1) + return ticks() / den; + else + return ticks() * num / den; + } + + duration_type d_; + }; + + // Convert to POSIX duration type. + static posix_time_duration to_posix_duration(const duration_type& d) + { + return posix_time_duration(WaitTraits::to_wait_duration(d)); + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP
diff --git a/boost/boost/asio/detail/completion_handler.hpp b/boost/boost/asio/detail/completion_handler.hpp new file mode 100644 index 0000000..3ad0ae8 --- /dev/null +++ b/boost/boost/asio/detail/completion_handler.hpp
@@ -0,0 +1,83 @@ +// +// detail/completion_handler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_COMPLETION_HANDLER_HPP +#define BOOST_ASIO_DETAIL_COMPLETION_HANDLER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/addressof.hpp> +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/fenced_block.hpp> +#include <boost/asio/detail/handler_alloc_helpers.hpp> +#include <boost/asio/detail/handler_invoke_helpers.hpp> +#include <boost/asio/detail/operation.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Handler> +class completion_handler : public operation +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(completion_handler); + + completion_handler(Handler& h) + : operation(&completion_handler::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(h)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + completion_handler* h(static_cast<completion_handler*>(base)); + ptr p = { boost::asio::detail::addressof(h->handler_), h, h }; + + BOOST_ASIO_HANDLER_COMPLETION((h)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + Handler handler(BOOST_ASIO_MOVE_CAST(Handler)(h->handler_)); + p.h = boost::asio::detail::addressof(handler); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN(()); + boost_asio_handler_invoke_helpers::invoke(handler, handler); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_COMPLETION_HANDLER_HPP
diff --git a/boost/boost/asio/detail/config.hpp b/boost/boost/asio/detail/config.hpp new file mode 100644 index 0000000..0f9e52d --- /dev/null +++ b/boost/boost/asio/detail/config.hpp
@@ -0,0 +1,971 @@ +// +// detail/config.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_CONFIG_HPP +#define BOOST_ASIO_DETAIL_CONFIG_HPP + +#if defined(BOOST_ASIO_STANDALONE) +# define BOOST_ASIO_DISABLE_BOOST_ARRAY 1 +# define BOOST_ASIO_DISABLE_BOOST_ASSERT 1 +# define BOOST_ASIO_DISABLE_BOOST_BIND 1 +# define BOOST_ASIO_DISABLE_BOOST_CHRONO 1 +# define BOOST_ASIO_DISABLE_BOOST_DATE_TIME 1 +# define BOOST_ASIO_DISABLE_BOOST_LIMITS 1 +# define BOOST_ASIO_DISABLE_BOOST_REGEX 1 +# define BOOST_ASIO_DISABLE_BOOST_STATIC_CONSTANT 1 +# define BOOST_ASIO_DISABLE_BOOST_THROW_EXCEPTION 1 +# define BOOST_ASIO_DISABLE_BOOST_WORKAROUND 1 +#else // defined(BOOST_ASIO_STANDALONE) +# include <boost/config.hpp> +# include <boost/version.hpp> +# define BOOST_ASIO_HAS_BOOST_CONFIG 1 +#endif // defined(BOOST_ASIO_STANDALONE) + +// Default to a header-only implementation. The user must specifically request +// separate compilation by defining either BOOST_ASIO_SEPARATE_COMPILATION or +// BOOST_ASIO_DYN_LINK (as a DLL/shared library implies separate compilation). +#if !defined(BOOST_ASIO_HEADER_ONLY) +# if !defined(BOOST_ASIO_SEPARATE_COMPILATION) +# if !defined(BOOST_ASIO_DYN_LINK) +# define BOOST_ASIO_HEADER_ONLY 1 +# endif // !defined(BOOST_ASIO_DYN_LINK) +# endif // !defined(BOOST_ASIO_SEPARATE_COMPILATION) +#endif // !defined(BOOST_ASIO_HEADER_ONLY) + +#if defined(BOOST_ASIO_HEADER_ONLY) +# define BOOST_ASIO_DECL inline +#else // defined(BOOST_ASIO_HEADER_ONLY) +# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CODEGEARC__) +// We need to import/export our code only if the user has specifically asked +// for it by defining BOOST_ASIO_DYN_LINK. +# if defined(BOOST_ASIO_DYN_LINK) +// Export if this is our own source, otherwise import. +# if defined(BOOST_ASIO_SOURCE) +# define BOOST_ASIO_DECL __declspec(dllexport) +# else // defined(BOOST_ASIO_SOURCE) +# define BOOST_ASIO_DECL __declspec(dllimport) +# endif // defined(BOOST_ASIO_SOURCE) +# endif // defined(BOOST_ASIO_DYN_LINK) +# endif // defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CODEGEARC__) +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +// If BOOST_ASIO_DECL isn't defined yet define it now. +#if !defined(BOOST_ASIO_DECL) +# define BOOST_ASIO_DECL +#endif // !defined(BOOST_ASIO_DECL) + +// Microsoft Visual C++ detection. +#if !defined(BOOST_ASIO_MSVC) +# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_MSVC) +# define BOOST_ASIO_MSVC BOOST_MSVC +# elif defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__EDG_VERSION__) +# define BOOST_ASIO_MSVC _MSC_VER +# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_MSVC) +#endif // defined(BOOST_ASIO_MSVC) + +// Clang / libc++ detection. +#if defined(__clang__) +# if (__cplusplus >= 201103) +# if __has_include(<__config>) +# include <__config> +# if defined(_LIBCPP_VERSION) +# define BOOST_ASIO_HAS_CLANG_LIBCXX 1 +# endif // defined(_LIBCPP_VERSION) +# endif // __has_include(<__config>) +# endif // (__cplusplus >= 201103) +#endif // defined(__clang__) + +// Support move construction and assignment on compilers known to allow it. +#if !defined(BOOST_ASIO_HAS_MOVE) +# if !defined(BOOST_ASIO_DISABLE_MOVE) +# if defined(__clang__) +# if __has_feature(__cxx_rvalue_references__) +# define BOOST_ASIO_HAS_MOVE 1 +# endif // __has_feature(__cxx_rvalue_references__) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_MOVE 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_MOVE 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_MOVE) +#endif // !defined(BOOST_ASIO_HAS_MOVE) + +// If BOOST_ASIO_MOVE_CAST isn't defined, and move support is available, define +// BOOST_ASIO_MOVE_ARG and BOOST_ASIO_MOVE_CAST to take advantage of rvalue +// references and perfect forwarding. +#if defined(BOOST_ASIO_HAS_MOVE) && !defined(BOOST_ASIO_MOVE_CAST) +# define BOOST_ASIO_MOVE_ARG(type) type&& +# define BOOST_ASIO_MOVE_CAST(type) static_cast<type&&> +# define BOOST_ASIO_MOVE_CAST2(type1, type2) static_cast<type1, type2&&> +#endif // defined(BOOST_ASIO_HAS_MOVE) && !defined(BOOST_ASIO_MOVE_CAST) + +// If BOOST_ASIO_MOVE_CAST still isn't defined, default to a C++03-compatible +// implementation. Note that older g++ and MSVC versions don't like it when you +// pass a non-member function through a const reference, so for most compilers +// we'll play it safe and stick with the old approach of passing the handler by +// value. +#if !defined(BOOST_ASIO_MOVE_CAST) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# define BOOST_ASIO_MOVE_ARG(type) const type& +# else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# define BOOST_ASIO_MOVE_ARG(type) type +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) +# elif defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1400) +# define BOOST_ASIO_MOVE_ARG(type) const type& +# else // (_MSC_VER >= 1400) +# define BOOST_ASIO_MOVE_ARG(type) type +# endif // (_MSC_VER >= 1400) +# else +# define BOOST_ASIO_MOVE_ARG(type) type +# endif +# define BOOST_ASIO_MOVE_CAST(type) static_cast<const type&> +# define BOOST_ASIO_MOVE_CAST2(type1, type2) static_cast<const type1, type2&> +#endif // !defined(BOOST_ASIO_MOVE_CAST) + +// Support variadic templates on compilers known to allow it. +#if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) +# if !defined(BOOST_ASIO_DISABLE_VARIADIC_TEMPLATES) +# if defined(__clang__) +# if __has_feature(__cxx_variadic_templates__) +# define BOOST_ASIO_HAS_VARIADIC_TEMPLATES 1 +# endif // __has_feature(__cxx_variadic_templates__) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_VARIADIC_TEMPLATES 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(BOOST_ASIO_DISABLE_VARIADIC_TEMPLATES) +#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) + +// Support constexpr on compilers known to allow it. +#if !defined(BOOST_ASIO_HAS_CONSTEXPR) +# if !defined(BOOST_ASIO_DISABLE_CONSTEXPR) +# if defined(__clang__) +# if __has_feature(__cxx_constexpr__) +# define BOOST_ASIO_HAS_CONSTEXPR 1 +# endif // __has_feature(__cxx_constexr__) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_CONSTEXPR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# endif // !defined(BOOST_ASIO_DISABLE_CONSTEXPR) +#endif // !defined(BOOST_ASIO_HAS_CONSTEXPR) +#if !defined(BOOST_ASIO_CONSTEXPR) +# if defined(BOOST_ASIO_HAS_CONSTEXPR) +# define BOOST_ASIO_CONSTEXPR constexpr +# else // defined(BOOST_ASIO_HAS_CONSTEXPR) +# define BOOST_ASIO_CONSTEXPR +# endif // defined(BOOST_ASIO_HAS_CONSTEXPR) +#endif // !defined(BOOST_ASIO_CONSTEXPR) + +// Standard library support for system errors. +# if !defined(BOOST_ASIO_DISABLE_STD_SYSTEM_ERROR) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_SYSTEM_ERROR 1 +# elif (__cplusplus >= 201103) +# if __has_include(<system_error>) +# define BOOST_ASIO_HAS_STD_SYSTEM_ERROR 1 +# endif // __has_include(<system_error>) +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_SYSTEM_ERROR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_SYSTEM_ERROR 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# 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(__clang__) +# if __has_feature(__cxx_noexcept__) +# define BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true) +# endif // __has_feature(__cxx_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_MSVC) +# if (_MSC_VER >= 1900) +# define BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true) +# endif // (_MSC_VER >= 1900) +# endif // defined(BOOST_ASIO_MSVC) +# 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_HAS_STD_ARRAY) +# if !defined(BOOST_ASIO_DISABLE_STD_ARRAY) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_ARRAY 1 +# elif (__cplusplus >= 201103) +# if __has_include(<array>) +# define BOOST_ASIO_HAS_STD_ARRAY 1 +# endif // __has_include(<array>) +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_ARRAY 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1600) +# define BOOST_ASIO_HAS_STD_ARRAY 1 +# endif // (_MSC_VER >= 1600) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_ARRAY) +#endif // !defined(BOOST_ASIO_HAS_STD_ARRAY) + +// Standard library support for shared_ptr and weak_ptr. +#if !defined(BOOST_ASIO_HAS_STD_SHARED_PTR) +# if !defined(BOOST_ASIO_DISABLE_STD_SHARED_PTR) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_SHARED_PTR 1 +# elif (__cplusplus >= 201103) +# define BOOST_ASIO_HAS_STD_SHARED_PTR 1 +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_SHARED_PTR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1600) +# define BOOST_ASIO_HAS_STD_SHARED_PTR 1 +# endif // (_MSC_VER >= 1600) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_SHARED_PTR) +#endif // !defined(BOOST_ASIO_HAS_STD_SHARED_PTR) + +// Standard library support for atomic operations. +#if !defined(BOOST_ASIO_HAS_STD_ATOMIC) +# if !defined(BOOST_ASIO_DISABLE_STD_ATOMIC) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_ATOMIC 1 +# elif (__cplusplus >= 201103) +# if __has_include(<atomic>) +# define BOOST_ASIO_HAS_STD_ATOMIC 1 +# endif // __has_include(<atomic>) +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_ATOMIC 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_ATOMIC 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_ATOMIC) +#endif // !defined(BOOST_ASIO_HAS_STD_ATOMIC) + +// Standard library support for chrono. Some standard libraries (such as the +// libstdc++ shipped with gcc 4.6) provide monotonic_clock as per early C++0x +// drafts, rather than the eventually standardised name of steady_clock. +#if !defined(BOOST_ASIO_HAS_STD_CHRONO) +# if !defined(BOOST_ASIO_DISABLE_STD_CHRONO) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_CHRONO 1 +# elif (__cplusplus >= 201103) +# if __has_include(<chrono>) +# define BOOST_ASIO_HAS_STD_CHRONO 1 +# endif // __has_include(<chrono>) +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_CHRONO 1 +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6)) +# define BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK 1 +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6)) +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_CHRONO 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_CHRONO) +#endif // !defined(BOOST_ASIO_HAS_STD_CHRONO) + +// Boost support for chrono. +#if !defined(BOOST_ASIO_HAS_BOOST_CHRONO) +# if !defined(BOOST_ASIO_DISABLE_BOOST_CHRONO) +# if (BOOST_VERSION >= 104700) +# define BOOST_ASIO_HAS_BOOST_CHRONO 1 +# endif // (BOOST_VERSION >= 104700) +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_CHRONO) +#endif // !defined(BOOST_ASIO_HAS_BOOST_CHRONO) + +// Boost support for the DateTime library. +#if !defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) +# if !defined(BOOST_ASIO_DISABLE_BOOST_DATE_TIME) +# define BOOST_ASIO_HAS_BOOST_DATE_TIME 1 +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_DATE_TIME) +#endif // !defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) + +// Standard library support for addressof. +#if !defined(BOOST_ASIO_HAS_STD_ADDRESSOF) +# if !defined(BOOST_ASIO_DISABLE_STD_ADDRESSOF) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_ADDRESSOF 1 +# elif (__cplusplus >= 201103) +# define BOOST_ASIO_HAS_STD_ADDRESSOF 1 +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_ADDRESSOF 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_ADDRESSOF 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_ADDRESSOF) +#endif // !defined(BOOST_ASIO_HAS_STD_ADDRESSOF) + +// Standard library support for the function class. +#if !defined(BOOST_ASIO_HAS_STD_FUNCTION) +# if !defined(BOOST_ASIO_DISABLE_STD_FUNCTION) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_FUNCTION 1 +# elif (__cplusplus >= 201103) +# define BOOST_ASIO_HAS_STD_FUNCTION 1 +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_FUNCTION 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_FUNCTION 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_FUNCTION) +#endif // !defined(BOOST_ASIO_HAS_STD_FUNCTION) + +// Standard library support for type traits. +#if !defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) +# if !defined(BOOST_ASIO_DISABLE_STD_TYPE_TRAITS) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_TYPE_TRAITS 1 +# elif (__cplusplus >= 201103) +# if __has_include(<type_traits>) +# define BOOST_ASIO_HAS_STD_TYPE_TRAITS 1 +# endif // __has_include(<type_traits>) +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_TYPE_TRAITS 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_TYPE_TRAITS 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_TYPE_TRAITS) +#endif // !defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) + +// Standard library support for the cstdint header. +#if !defined(BOOST_ASIO_HAS_CSTDINT) +# if !defined(BOOST_ASIO_DISABLE_CSTDINT) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_CSTDINT 1 +# elif (__cplusplus >= 201103) +# define BOOST_ASIO_HAS_CSTDINT 1 +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_CSTDINT 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_CSTDINT 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_CSTDINT) +#endif // !defined(BOOST_ASIO_HAS_CSTDINT) + +// Standard library support for the thread class. +#if !defined(BOOST_ASIO_HAS_STD_THREAD) +# if !defined(BOOST_ASIO_DISABLE_STD_THREAD) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_THREAD 1 +# elif (__cplusplus >= 201103) +# if __has_include(<thread>) +# define BOOST_ASIO_HAS_STD_THREAD 1 +# endif // __has_include(<thread>) +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_THREAD 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_THREAD 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_THREAD) +#endif // !defined(BOOST_ASIO_HAS_STD_THREAD) + +// Standard library support for the mutex and condition variable classes. +#if !defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +# if !defined(BOOST_ASIO_DISABLE_STD_MUTEX_AND_CONDVAR) +# if defined(__clang__) +# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX) +# define BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 +# elif (__cplusplus >= 201103) +# if __has_include(<mutex>) +# define BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 +# endif // __has_include(<mutex>) +# endif // (__cplusplus >= 201103) +# endif // defined(__clang__) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) +# endif // !defined(BOOST_ASIO_DISABLE_STD_MUTEX_AND_CONDVAR) +#endif // !defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) + +// WinRT target. +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) +# if defined(__cplusplus_winrt) +# include <winapifamily.h> +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) \ + && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define BOOST_ASIO_WINDOWS_RUNTIME 1 +# endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) + // && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# endif // defined(__cplusplus_winrt) +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +// Windows target. Excludes WinRT. +#if !defined(BOOST_ASIO_WINDOWS) +# if !defined(BOOST_ASIO_WINDOWS_RUNTIME) +# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS) +# define BOOST_ASIO_WINDOWS 1 +# elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# define BOOST_ASIO_WINDOWS 1 +# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS) +# endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) +#endif // !defined(BOOST_ASIO_WINDOWS) + +// Windows: target OS version. +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) +# if defined(_MSC_VER) || defined(__BORLANDC__) +# pragma message( \ + "Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\ + "- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\ + "- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\ + "Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).") +# else // defined(_MSC_VER) || defined(__BORLANDC__) +# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. +# warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line. +# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target). +# endif // defined(_MSC_VER) || defined(__BORLANDC__) +# define _WIN32_WINNT 0x0501 +# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) +# if defined(_MSC_VER) +# if defined(_WIN32) && !defined(WIN32) +# if !defined(_WINSOCK2API_) +# define WIN32 // Needed for correct types in winsock2.h +# else // !defined(_WINSOCK2API_) +# error Please define the macro WIN32 in your compiler options +# endif // !defined(_WINSOCK2API_) +# endif // defined(_WIN32) && !defined(WIN32) +# endif // defined(_MSC_VER) +# if defined(__BORLANDC__) +# if defined(__WIN32__) && !defined(WIN32) +# if !defined(_WINSOCK2API_) +# define WIN32 // Needed for correct types in winsock2.h +# else // !defined(_WINSOCK2API_) +# error Please define the macro WIN32 in your compiler options +# endif // !defined(_WINSOCK2API_) +# endif // defined(__WIN32__) && !defined(WIN32) +# endif // defined(__BORLANDC__) +# if defined(__CYGWIN__) +# if !defined(__USE_W32_SOCKETS) +# error You must add -D__USE_W32_SOCKETS to your compiler options. +# endif // !defined(__USE_W32_SOCKETS) +# endif // defined(__CYGWIN__) +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + +// Windows: minimise header inclusion. +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +# if !defined(BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN) +# if !defined(WIN32_LEAN_AND_MEAN) +# define WIN32_LEAN_AND_MEAN +# endif // !defined(WIN32_LEAN_AND_MEAN) +# endif // !defined(BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN) +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + +// Windows: suppress definition of "min" and "max" macros. +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +# if !defined(BOOST_ASIO_NO_NOMINMAX) +# if !defined(NOMINMAX) +# define NOMINMAX 1 +# endif // !defined(NOMINMAX) +# endif // !defined(BOOST_ASIO_NO_NOMINMAX) +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + +// Windows: IO Completion Ports. +#if !defined(BOOST_ASIO_HAS_IOCP) +# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) +# if !defined(UNDER_CE) +# if !defined(BOOST_ASIO_DISABLE_IOCP) +# define BOOST_ASIO_HAS_IOCP 1 +# endif // !defined(BOOST_ASIO_DISABLE_IOCP) +# endif // !defined(UNDER_CE) +# endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) +# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_HAS_IOCP) + +// On POSIX (and POSIX-like) platforms we need to include unistd.h in order to +// get access to the various platform feature macros, e.g. to be able to test +// for threads support. +#if !defined(BOOST_ASIO_HAS_UNISTD_H) +# if !defined(BOOST_ASIO_HAS_BOOST_CONFIG) +# if defined(unix) \ + || defined(__unix) \ + || defined(_XOPEN_SOURCE) \ + || defined(_POSIX_SOURCE) \ + || (defined(__MACH__) && defined(__APPLE__)) \ + || defined(__FreeBSD__) \ + || defined(__NetBSD__) \ + || defined(__OpenBSD__) \ + || defined(__linux__) +# define BOOST_ASIO_HAS_UNISTD_H 1 +# endif +# endif // !defined(BOOST_ASIO_HAS_BOOST_CONFIG) +#endif // !defined(BOOST_ASIO_HAS_UNISTD_H) +#if defined(BOOST_ASIO_HAS_UNISTD_H) +# include <unistd.h> +#endif // defined(BOOST_ASIO_HAS_UNISTD_H) + +// Linux: epoll, eventfd and timerfd. +#if defined(__linux__) +# include <linux/version.h> +# if !defined(BOOST_ASIO_HAS_EPOLL) +# if !defined(BOOST_ASIO_DISABLE_EPOLL) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) +# define BOOST_ASIO_HAS_EPOLL 1 +# endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45) +# endif // !defined(BOOST_ASIO_DISABLE_EPOLL) +# endif // !defined(BOOST_ASIO_HAS_EPOLL) +# if !defined(BOOST_ASIO_HAS_EVENTFD) +# if !defined(BOOST_ASIO_DISABLE_EVENTFD) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +# define BOOST_ASIO_HAS_EVENTFD 1 +# endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +# endif // !defined(BOOST_ASIO_DISABLE_EVENTFD) +# endif // !defined(BOOST_ASIO_HAS_EVENTFD) +# if !defined(BOOST_ASIO_HAS_TIMERFD) +# if defined(BOOST_ASIO_HAS_EPOLL) +# if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) +# define BOOST_ASIO_HAS_TIMERFD 1 +# endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) +# endif // defined(BOOST_ASIO_HAS_EPOLL) +# endif // !defined(BOOST_ASIO_HAS_TIMERFD) +#endif // defined(__linux__) + +// Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue. +#if (defined(__MACH__) && defined(__APPLE__)) \ + || defined(__FreeBSD__) \ + || defined(__NetBSD__) \ + || defined(__OpenBSD__) +# if !defined(BOOST_ASIO_HAS_KQUEUE) +# if !defined(BOOST_ASIO_DISABLE_KQUEUE) +# define BOOST_ASIO_HAS_KQUEUE 1 +# endif // !defined(BOOST_ASIO_DISABLE_KQUEUE) +# endif // !defined(BOOST_ASIO_HAS_KQUEUE) +#endif // (defined(__MACH__) && defined(__APPLE__)) + // || defined(__FreeBSD__) + // || defined(__NetBSD__) + // || defined(__OpenBSD__) + +// Solaris: /dev/poll. +#if defined(__sun) +# if !defined(BOOST_ASIO_HAS_DEV_POLL) +# if !defined(BOOST_ASIO_DISABLE_DEV_POLL) +# define BOOST_ASIO_HAS_DEV_POLL 1 +# endif // !defined(BOOST_ASIO_DISABLE_DEV_POLL) +# endif // !defined(BOOST_ASIO_HAS_DEV_POLL) +#endif // defined(__sun) + +// Serial ports. +#if !defined(BOOST_ASIO_HAS_SERIAL_PORT) +# if defined(BOOST_ASIO_HAS_IOCP) \ + || !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) +# if !defined(__SYMBIAN32__) +# if !defined(BOOST_ASIO_DISABLE_SERIAL_PORT) +# define BOOST_ASIO_HAS_SERIAL_PORT 1 +# endif // !defined(BOOST_ASIO_DISABLE_SERIAL_PORT) +# endif // !defined(__SYMBIAN32__) +# endif // defined(BOOST_ASIO_HAS_IOCP) + // || !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_HAS_SERIAL_PORT) + +// Windows: stream handles. +#if !defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) +# if !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE) +# if defined(BOOST_ASIO_HAS_IOCP) +# define BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE 1 +# endif // defined(BOOST_ASIO_HAS_IOCP) +# endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE) +#endif // !defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) + +// Windows: random access handles. +#if !defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) +# if !defined(BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +# if defined(BOOST_ASIO_HAS_IOCP) +# define BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1 +# endif // defined(BOOST_ASIO_HAS_IOCP) +# endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE) +#endif // !defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + +// Windows: object handles. +#if !defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) +# if !defined(BOOST_ASIO_DISABLE_WINDOWS_OBJECT_HANDLE) +# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +# if !defined(UNDER_CE) +# define BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE 1 +# endif // !defined(UNDER_CE) +# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +# endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_OBJECT_HANDLE) +#endif // !defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) + +// Windows: OVERLAPPED wrapper. +#if !defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR) +# if !defined(BOOST_ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR) +# if defined(BOOST_ASIO_HAS_IOCP) +# define BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR 1 +# endif // defined(BOOST_ASIO_HAS_IOCP) +# endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR) +#endif // !defined(BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR) + +// POSIX: stream-oriented file descriptors. +#if !defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +# if !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) +# if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) +# define BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1 +# endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +# endif // !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR) +#endif // !defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + +// UNIX domain sockets. +#if !defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) +# if !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS) +# if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) +# define BOOST_ASIO_HAS_LOCAL_SOCKETS 1 +# endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +# endif // !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS) +#endif // !defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) + +// Can use sigaction() instead of signal(). +#if !defined(BOOST_ASIO_HAS_SIGACTION) +# if !defined(BOOST_ASIO_DISABLE_SIGACTION) +# if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) +# define BOOST_ASIO_HAS_SIGACTION 1 +# endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +# endif // !defined(BOOST_ASIO_DISABLE_SIGACTION) +#endif // !defined(BOOST_ASIO_HAS_SIGACTION) + +// Can use signal(). +#if !defined(BOOST_ASIO_HAS_SIGNAL) +# if !defined(BOOST_ASIO_DISABLE_SIGNAL) +# if !defined(UNDER_CE) +# define BOOST_ASIO_HAS_SIGNAL 1 +# endif // !defined(UNDER_CE) +# endif // !defined(BOOST_ASIO_DISABLE_SIGNAL) +#endif // !defined(BOOST_ASIO_HAS_SIGNAL) + +// Can use getaddrinfo() and getnameinfo(). +#if !defined(BOOST_ASIO_HAS_GETADDRINFO) +# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) +# define BOOST_ASIO_HAS_GETADDRINFO 1 +# elif defined(UNDER_CE) +# define BOOST_ASIO_HAS_GETADDRINFO 1 +# endif // defined(UNDER_CE) +# elif !(defined(__MACH__) && defined(__APPLE__)) +# define BOOST_ASIO_HAS_GETADDRINFO 1 +# endif // !(defined(__MACH__) && defined(__APPLE__)) +#endif // !defined(BOOST_ASIO_HAS_GETADDRINFO) + +// Whether standard iostreams are disabled. +#if !defined(BOOST_ASIO_NO_IOSTREAM) +# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_NO_IOSTREAM) +# define BOOST_ASIO_NO_IOSTREAM 1 +# endif // !defined(BOOST_NO_IOSTREAM) +#endif // !defined(BOOST_ASIO_NO_IOSTREAM) + +// Whether exception handling is disabled. +#if !defined(BOOST_ASIO_NO_EXCEPTIONS) +# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_NO_EXCEPTIONS) +# define BOOST_ASIO_NO_EXCEPTIONS 1 +# endif // !defined(BOOST_NO_EXCEPTIONS) +#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS) + +// Whether the typeid operator is supported. +#if !defined(BOOST_ASIO_NO_TYPEID) +# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_NO_TYPEID) +# define BOOST_ASIO_NO_TYPEID 1 +# endif // !defined(BOOST_NO_TYPEID) +#endif // !defined(BOOST_ASIO_NO_TYPEID) + +// Threads. +#if !defined(BOOST_ASIO_HAS_THREADS) +# if !defined(BOOST_ASIO_DISABLE_THREADS) +# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_THREADS) +# define BOOST_ASIO_HAS_THREADS 1 +# elif defined(_MSC_VER) && defined(_MT) +# define BOOST_ASIO_HAS_THREADS 1 +# elif defined(__BORLANDC__) && defined(__MT__) +# define BOOST_ASIO_HAS_THREADS 1 +# elif defined(_POSIX_THREADS) +# define BOOST_ASIO_HAS_THREADS 1 +# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_THREADS) +# endif // !defined(BOOST_ASIO_DISABLE_THREADS) +#endif // !defined(BOOST_ASIO_HAS_THREADS) + +// POSIX threads. +#if !defined(BOOST_ASIO_HAS_PTHREADS) +# if defined(BOOST_ASIO_HAS_THREADS) +# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS) +# define BOOST_ASIO_HAS_PTHREADS 1 +# elif defined(_POSIX_THREADS) +# define BOOST_ASIO_HAS_PTHREADS 1 +# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS) +# endif // defined(BOOST_ASIO_HAS_THREADS) +#endif // !defined(BOOST_ASIO_HAS_PTHREADS) + +// Helper to prevent macro expansion. +#define BOOST_ASIO_PREVENT_MACRO_SUBSTITUTION + +// Helper to define in-class constants. +#if !defined(BOOST_ASIO_STATIC_CONSTANT) +# if !defined(BOOST_ASIO_DISABLE_BOOST_STATIC_CONSTANT) +# define BOOST_ASIO_STATIC_CONSTANT(type, assignment) \ + BOOST_STATIC_CONSTANT(type, assignment) +# else // !defined(BOOST_ASIO_DISABLE_BOOST_STATIC_CONSTANT) +# define BOOST_ASIO_STATIC_CONSTANT(type, assignment) \ + static const type assignment +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_STATIC_CONSTANT) +#endif // !defined(BOOST_ASIO_STATIC_CONSTANT) + +// Boost array library. +#if !defined(BOOST_ASIO_HAS_BOOST_ARRAY) +# if !defined(BOOST_ASIO_DISABLE_BOOST_ARRAY) +# define BOOST_ASIO_HAS_BOOST_ARRAY 1 +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_ARRAY) +#endif // !defined(BOOST_ASIO_HAS_BOOST_ARRAY) + +// Boost assert macro. +#if !defined(BOOST_ASIO_HAS_BOOST_ASSERT) +# if !defined(BOOST_ASIO_DISABLE_BOOST_ASSERT) +# define BOOST_ASIO_HAS_BOOST_ASSERT 1 +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_ASSERT) +#endif // !defined(BOOST_ASIO_HAS_BOOST_ASSERT) + +// Boost limits header. +#if !defined(BOOST_ASIO_HAS_BOOST_LIMITS) +# if !defined(BOOST_ASIO_DISABLE_BOOST_LIMITS) +# define BOOST_ASIO_HAS_BOOST_LIMITS 1 +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_LIMITS) +#endif // !defined(BOOST_ASIO_HAS_BOOST_LIMITS) + +// Boost throw_exception function. +#if !defined(BOOST_ASIO_HAS_BOOST_THROW_EXCEPTION) +# if !defined(BOOST_ASIO_DISABLE_BOOST_THROW_EXCEPTION) +# define BOOST_ASIO_HAS_BOOST_THROW_EXCEPTION 1 +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_THROW_EXCEPTION) +#endif // !defined(BOOST_ASIO_HAS_BOOST_THROW_EXCEPTION) + +// Boost regex library. +#if !defined(BOOST_ASIO_HAS_BOOST_REGEX) +# if !defined(BOOST_ASIO_DISABLE_BOOST_REGEX) +# define BOOST_ASIO_HAS_BOOST_REGEX 1 +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_REGEX) +#endif // !defined(BOOST_ASIO_HAS_BOOST_REGEX) + +// Boost bind function. +#if !defined(BOOST_ASIO_HAS_BOOST_BIND) +# if !defined(BOOST_ASIO_DISABLE_BOOST_BIND) +# define BOOST_ASIO_HAS_BOOST_BIND 1 +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_BIND) +#endif // !defined(BOOST_ASIO_HAS_BOOST_BIND) + +// Boost's BOOST_WORKAROUND macro. +#if !defined(BOOST_ASIO_HAS_BOOST_WORKAROUND) +# if !defined(BOOST_ASIO_DISABLE_BOOST_WORKAROUND) +# define BOOST_ASIO_HAS_BOOST_WORKAROUND 1 +# endif // !defined(BOOST_ASIO_DISABLE_BOOST_WORKAROUND) +#endif // !defined(BOOST_ASIO_HAS_BOOST_WORKAROUND) + +// Microsoft Visual C++'s secure C runtime library. +#if !defined(BOOST_ASIO_HAS_SECURE_RTL) +# if !defined(BOOST_ASIO_DISABLE_SECURE_RTL) +# if defined(BOOST_ASIO_MSVC) \ + && (BOOST_ASIO_MSVC >= 1400) \ + && !defined(UNDER_CE) +# define BOOST_ASIO_HAS_SECURE_RTL 1 +# endif // defined(BOOST_ASIO_MSVC) + // && (BOOST_ASIO_MSVC >= 1400) + // && !defined(UNDER_CE) +# endif // !defined(BOOST_ASIO_DISABLE_SECURE_RTL) +#endif // !defined(BOOST_ASIO_HAS_SECURE_RTL) + +// Handler hooking. Disabled for ancient Borland C++ and gcc compilers. +#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS) +# if !defined(BOOST_ASIO_DISABLE_HANDLER_HOOKS) +# if defined(__GNUC__) +# if (__GNUC__ >= 3) +# define BOOST_ASIO_HAS_HANDLER_HOOKS 1 +# endif // (__GNUC__ >= 3) +# elif !defined(__BORLANDC__) +# define BOOST_ASIO_HAS_HANDLER_HOOKS 1 +# endif // !defined(__BORLANDC__) +# endif // !defined(BOOST_ASIO_DISABLE_HANDLER_HOOKS) +#endif // !defined(BOOST_ASIO_HAS_HANDLER_HOOKS) + +// 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 +# define BOOST_ASIO_THREAD_KEYWORD __thread +# 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__) +# if defined(BOOST_ASIO_MSVC) && defined(BOOST_ASIO_WINDOWS_RUNTIME) +# if (_MSC_VER >= 1700) +# define BOOST_ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 +# define BOOST_ASIO_THREAD_KEYWORD __declspec(thread) +# endif // (_MSC_VER >= 1700) +# endif // defined(BOOST_ASIO_MSVC) && defined(BOOST_ASIO_WINDOWS_RUNTIME) +#endif // !defined(BOOST_ASIO_DISABLE_THREAD_KEYWORD_EXTENSION) +#if !defined(BOOST_ASIO_THREAD_KEYWORD) +# define BOOST_ASIO_THREAD_KEYWORD __thread +#endif // !defined(BOOST_ASIO_THREAD_KEYWORD) + +// 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
diff --git a/boost/boost/asio/detail/consuming_buffers.hpp b/boost/boost/asio/detail/consuming_buffers.hpp new file mode 100644 index 0000000..7a02271 --- /dev/null +++ b/boost/boost/asio/detail/consuming_buffers.hpp
@@ -0,0 +1,294 @@ +// +// detail/consuming_buffers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP +#define BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <iterator> +#include <boost/asio/buffer.hpp> +#include <boost/asio/detail/limits.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +// A proxy iterator for a sub-range in a list of buffers. +template <typename Buffer, typename Buffer_Iterator> +class consuming_buffers_iterator +{ +public: + /// The type used for the distance between two iterators. + typedef std::ptrdiff_t difference_type; + + /// The type of the value pointed to by the iterator. + typedef Buffer value_type; + + /// The type of the result of applying operator->() to the iterator. + typedef const Buffer* pointer; + + /// The type of the result of applying operator*() to the iterator. + typedef const Buffer& reference; + + /// The iterator category. + typedef std::forward_iterator_tag iterator_category; + + // Default constructor creates an end iterator. + consuming_buffers_iterator() + : at_end_(true) + { + } + + // Construct with a buffer for the first entry and an iterator + // range for the remaining entries. + consuming_buffers_iterator(bool at_end, const Buffer& first, + Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder, + std::size_t max_size) + : at_end_(max_size > 0 ? at_end : true), + first_(buffer(first, max_size)), + begin_remainder_(begin_remainder), + end_remainder_(end_remainder), + offset_(0), + max_size_(max_size) + { + } + + // Dereference an iterator. + const Buffer& operator*() const + { + return dereference(); + } + + // Dereference an iterator. + const Buffer* operator->() const + { + return &dereference(); + } + + // Increment operator (prefix). + consuming_buffers_iterator& operator++() + { + increment(); + return *this; + } + + // Increment operator (postfix). + consuming_buffers_iterator operator++(int) + { + consuming_buffers_iterator tmp(*this); + ++*this; + return tmp; + } + + // Test two iterators for equality. + friend bool operator==(const consuming_buffers_iterator& a, + const consuming_buffers_iterator& b) + { + return a.equal(b); + } + + // Test two iterators for inequality. + friend bool operator!=(const consuming_buffers_iterator& a, + const consuming_buffers_iterator& b) + { + return !a.equal(b); + } + +private: + void increment() + { + if (!at_end_) + { + if (begin_remainder_ == end_remainder_ + || offset_ + buffer_size(first_) >= max_size_) + { + at_end_ = true; + } + else + { + offset_ += buffer_size(first_); + first_ = buffer(*begin_remainder_++, max_size_ - offset_); + } + } + } + + bool equal(const consuming_buffers_iterator& other) const + { + if (at_end_ && other.at_end_) + return true; + return !at_end_ && !other.at_end_ + && buffer_cast<const void*>(first_) + == buffer_cast<const void*>(other.first_) + && buffer_size(first_) == buffer_size(other.first_) + && begin_remainder_ == other.begin_remainder_ + && end_remainder_ == other.end_remainder_; + } + + const Buffer& dereference() const + { + return first_; + } + + bool at_end_; + Buffer first_; + Buffer_Iterator begin_remainder_; + Buffer_Iterator end_remainder_; + std::size_t offset_; + std::size_t max_size_; +}; + +// A proxy for a sub-range in a list of buffers. +template <typename Buffer, typename Buffers> +class consuming_buffers +{ +public: + // The type for each element in the list of buffers. + typedef Buffer value_type; + + // A forward-only iterator type that may be used to read elements. + typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator> + const_iterator; + + // Construct to represent the entire list of buffers. + consuming_buffers(const Buffers& buffers) + : buffers_(buffers), + at_end_(buffers_.begin() == buffers_.end()), + begin_remainder_(buffers_.begin()), + max_size_((std::numeric_limits<std::size_t>::max)()) + { + if (!at_end_) + { + first_ = *buffers_.begin(); + ++begin_remainder_; + } + } + + // Copy constructor. + consuming_buffers(const consuming_buffers& other) + : buffers_(other.buffers_), + at_end_(other.at_end_), + first_(other.first_), + begin_remainder_(buffers_.begin()), + max_size_(other.max_size_) + { + typename Buffers::const_iterator first = other.buffers_.begin(); + typename Buffers::const_iterator second = other.begin_remainder_; + std::advance(begin_remainder_, std::distance(first, second)); + } + + // Assignment operator. + consuming_buffers& operator=(const consuming_buffers& other) + { + buffers_ = other.buffers_; + at_end_ = other.at_end_; + first_ = other.first_; + begin_remainder_ = buffers_.begin(); + typename Buffers::const_iterator first = other.buffers_.begin(); + typename Buffers::const_iterator second = other.begin_remainder_; + std::advance(begin_remainder_, std::distance(first, second)); + max_size_ = other.max_size_; + return *this; + } + + // Get a forward-only iterator to the first element. + const_iterator begin() const + { + return const_iterator(at_end_, first_, + begin_remainder_, buffers_.end(), max_size_); + } + + // Get a forward-only iterator for one past the last element. + const_iterator end() const + { + return const_iterator(); + } + + // Set the maximum size for a single transfer. + void prepare(std::size_t max_size) + { + max_size_ = max_size; + } + + // Consume the specified number of bytes from the buffers. + void consume(std::size_t size) + { + // Remove buffers from the start until the specified size is reached. + while (size > 0 && !at_end_) + { + if (buffer_size(first_) <= size) + { + size -= buffer_size(first_); + if (begin_remainder_ == buffers_.end()) + at_end_ = true; + else + first_ = *begin_remainder_++; + } + else + { + first_ = first_ + size; + size = 0; + } + } + + // Remove any more empty buffers at the start. + while (!at_end_ && buffer_size(first_) == 0) + { + if (begin_remainder_ == buffers_.end()) + at_end_ = true; + else + first_ = *begin_remainder_++; + } + } + +private: + Buffers buffers_; + bool at_end_; + Buffer first_; + typename Buffers::const_iterator begin_remainder_; + std::size_t max_size_; +}; + +// Specialisation for null_buffers to ensure that the null_buffers type is +// always passed through to the underlying read or write operation. +template <typename Buffer> +class consuming_buffers<Buffer, boost::asio::null_buffers> + : public boost::asio::null_buffers +{ +public: + consuming_buffers(const boost::asio::null_buffers&) + { + // No-op. + } + + void prepare(std::size_t) + { + // No-op. + } + + void consume(std::size_t) + { + // No-op. + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP
diff --git a/boost/boost/asio/detail/cstdint.hpp b/boost/boost/asio/detail/cstdint.hpp new file mode 100644 index 0000000..1dfa6e0 --- /dev/null +++ b/boost/boost/asio/detail/cstdint.hpp
@@ -0,0 +1,48 @@ +// +// detail/cstdint.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_CSTDINT_HPP +#define BOOST_ASIO_DETAIL_CSTDINT_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_CSTDINT) +# include <cstdint> +#else // defined(BOOST_ASIO_HAS_CSTDINT) +# include <boost/cstdint.hpp> +#endif // defined(BOOST_ASIO_HAS_CSTDINT) + +namespace boost { +namespace asio { + +#if defined(BOOST_ASIO_HAS_CSTDINT) +using std::int16_t; +using std::uint16_t; +using std::int32_t; +using std::uint32_t; +using std::int64_t; +using std::uint64_t; +#else // defined(BOOST_ASIO_HAS_CSTDINT) +using boost::int16_t; +using boost::uint16_t; +using boost::int32_t; +using boost::uint32_t; +using boost::int64_t; +using boost::uint64_t; +#endif // defined(BOOST_ASIO_HAS_CSTDINT) + +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_CSTDINT_HPP
diff --git a/boost/boost/asio/detail/date_time_fwd.hpp b/boost/boost/asio/detail/date_time_fwd.hpp new file mode 100644 index 0000000..9c8a515 --- /dev/null +++ b/boost/boost/asio/detail/date_time_fwd.hpp
@@ -0,0 +1,34 @@ +// +// detail/date_time_fwd.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_DATE_TIME_FWD_HPP +#define BOOST_ASIO_DETAIL_DATE_TIME_FWD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +namespace boost { +namespace date_time { + +template<class T, class TimeSystem> +class base_time; + +} // namespace date_time +namespace posix_time { + +class ptime; + +} // namespace posix_time +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_DATE_TIME_FWD_HPP
diff --git a/boost/boost/asio/detail/deadline_timer_service.hpp b/boost/boost/asio/detail/deadline_timer_service.hpp new file mode 100644 index 0000000..74a3226 --- /dev/null +++ b/boost/boost/asio/detail/deadline_timer_service.hpp
@@ -0,0 +1,229 @@ +// +// detail/deadline_timer_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP +#define BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cstddef> +#include <boost/asio/error.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/detail/addressof.hpp> +#include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/fenced_block.hpp> +#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/detail/socket_ops.hpp> +#include <boost/asio/detail/socket_types.hpp> +#include <boost/asio/detail/timer_queue.hpp> +#include <boost/asio/detail/timer_scheduler.hpp> +#include <boost/asio/detail/wait_handler.hpp> +#include <boost/asio/detail/wait_op.hpp> + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include <chrono> +# include <thread> +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Time_Traits> +class deadline_timer_service +{ +public: + // The time type. + typedef typename Time_Traits::time_type time_type; + + // The duration type. + typedef typename Time_Traits::duration_type duration_type; + + // The implementation type of the timer. This type is dependent on the + // underlying implementation of the timer service. + struct implementation_type + : private boost::asio::detail::noncopyable + { + time_type expiry; + bool might_have_pending_waits; + typename timer_queue<Time_Traits>::per_timer_data timer_data; + }; + + // Constructor. + deadline_timer_service(boost::asio::io_service& io_service) + : scheduler_(boost::asio::use_service<timer_scheduler>(io_service)) + { + scheduler_.init_task(); + scheduler_.add_timer_queue(timer_queue_); + } + + // Destructor. + ~deadline_timer_service() + { + scheduler_.remove_timer_queue(timer_queue_); + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown_service() + { + } + + // Construct a new timer implementation. + void construct(implementation_type& impl) + { + impl.expiry = time_type(); + impl.might_have_pending_waits = false; + } + + // Destroy a timer implementation. + void destroy(implementation_type& impl) + { + boost::system::error_code ec; + cancel(impl, ec); + } + + // Cancel any asynchronous wait operations associated with the timer. + std::size_t cancel(implementation_type& impl, boost::system::error_code& ec) + { + if (!impl.might_have_pending_waits) + { + ec = boost::system::error_code(); + return 0; + } + + BOOST_ASIO_HANDLER_OPERATION(("deadline_timer", &impl, "cancel")); + + std::size_t count = scheduler_.cancel_timer(timer_queue_, impl.timer_data); + impl.might_have_pending_waits = false; + ec = boost::system::error_code(); + return count; + } + + // Cancels one asynchronous wait operation associated with the timer. + std::size_t cancel_one(implementation_type& impl, + boost::system::error_code& ec) + { + if (!impl.might_have_pending_waits) + { + ec = boost::system::error_code(); + return 0; + } + + BOOST_ASIO_HANDLER_OPERATION(("deadline_timer", &impl, "cancel_one")); + + std::size_t count = scheduler_.cancel_timer( + timer_queue_, impl.timer_data, 1); + if (count == 0) + impl.might_have_pending_waits = false; + ec = boost::system::error_code(); + return count; + } + + // Get the expiry time for the timer as an absolute time. + time_type expires_at(const implementation_type& impl) const + { + return impl.expiry; + } + + // Set the expiry time for the timer as an absolute time. + std::size_t expires_at(implementation_type& impl, + const time_type& expiry_time, boost::system::error_code& ec) + { + std::size_t count = cancel(impl, ec); + impl.expiry = expiry_time; + ec = boost::system::error_code(); + return count; + } + + // Get the expiry time for the timer relative to now. + duration_type expires_from_now(const implementation_type& impl) const + { + return Time_Traits::subtract(expires_at(impl), Time_Traits::now()); + } + + // Set the expiry time for the timer relative to now. + std::size_t expires_from_now(implementation_type& impl, + const duration_type& expiry_time, boost::system::error_code& ec) + { + return expires_at(impl, + Time_Traits::add(Time_Traits::now(), expiry_time), ec); + } + + // Perform a blocking wait on the timer. + void wait(implementation_type& impl, boost::system::error_code& ec) + { + time_type now = Time_Traits::now(); + ec = boost::system::error_code(); + while (Time_Traits::less_than(now, impl.expiry) && !ec) + { + this->do_wait(Time_Traits::to_posix_duration( + Time_Traits::subtract(impl.expiry, now)), ec); + now = Time_Traits::now(); + } + } + + // Start an asynchronous wait on the timer. + template <typename Handler> + void async_wait(implementation_type& impl, Handler& handler) + { + // Allocate and construct an operation to wrap the handler. + typedef wait_handler<Handler> op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + boost_asio_handler_alloc_helpers::allocate( + sizeof(op), handler), 0 }; + p.p = new (p.v) op(handler); + + impl.might_have_pending_waits = true; + + BOOST_ASIO_HANDLER_CREATION((p.p, "deadline_timer", &impl, "async_wait")); + + scheduler_.schedule_timer(timer_queue_, impl.expiry, impl.timer_data, p.p); + p.v = p.p = 0; + } + +private: + // Helper function to wait given a duration type. The duration type should + // either be of type boost::posix_time::time_duration, or implement the + // required subset of its interface. + template <typename Duration> + void do_wait(const Duration& timeout, boost::system::error_code& ec) + { +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + std::this_thread::sleep_for( + std::chrono::seconds(timeout.total_seconds()) + + std::chrono::microseconds(timeout.total_microseconds())); + ec = boost::system::error_code(); +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) + ::timeval tv; + tv.tv_sec = timeout.total_seconds(); + tv.tv_usec = timeout.total_microseconds() % 1000000; + socket_ops::select(0, 0, 0, 0, &tv, ec); +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + } + + // The queue of timers. + timer_queue<Time_Traits> timer_queue_; + + // The object that schedules and executes timers. Usually a reactor. + timer_scheduler& scheduler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
diff --git a/boost/boost/asio/detail/dependent_type.hpp b/boost/boost/asio/detail/dependent_type.hpp new file mode 100644 index 0000000..fb697d2 --- /dev/null +++ b/boost/boost/asio/detail/dependent_type.hpp
@@ -0,0 +1,38 @@ +// +// detail/dependent_type.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_DEPENDENT_TYPE_HPP +#define BOOST_ASIO_DETAIL_DEPENDENT_TYPE_HPP + +#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/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename DependsOn, typename T> +struct dependent_type +{ + typedef T type; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_DEPENDENT_TYPE_HPP
diff --git a/boost/boost/asio/detail/descriptor_ops.hpp b/boost/boost/asio/detail/descriptor_ops.hpp new file mode 100644 index 0000000..7ea2f07 --- /dev/null +++ b/boost/boost/asio/detail/descriptor_ops.hpp
@@ -0,0 +1,119 @@ +// +// detail/descriptor_ops.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP +#define BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + +#include <cstddef> +#include <boost/system/error_code.hpp> +#include <boost/asio/detail/socket_types.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { +namespace descriptor_ops { + +// Descriptor state bits. +enum +{ + // The user wants a non-blocking descriptor. + user_set_non_blocking = 1, + + // The descriptor has been set non-blocking. + internal_non_blocking = 2, + + // Helper "state" used to determine whether the descriptor is non-blocking. + non_blocking = user_set_non_blocking | internal_non_blocking, + + // The descriptor may have been dup()-ed. + possible_dup = 4 +}; + +typedef unsigned char state_type; + +template <typename ReturnType> +inline ReturnType error_wrapper(ReturnType return_value, + boost::system::error_code& ec) +{ + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); + return return_value; +} + +BOOST_ASIO_DECL int open(const char* path, int flags, + boost::system::error_code& ec); + +BOOST_ASIO_DECL int close(int d, state_type& state, + boost::system::error_code& ec); + +BOOST_ASIO_DECL bool set_user_non_blocking(int d, + state_type& state, bool value, boost::system::error_code& ec); + +BOOST_ASIO_DECL bool set_internal_non_blocking(int d, + state_type& state, bool value, boost::system::error_code& ec); + +typedef iovec buf; + +BOOST_ASIO_DECL std::size_t sync_read(int d, state_type state, buf* bufs, + std::size_t count, bool all_empty, boost::system::error_code& ec); + +BOOST_ASIO_DECL bool non_blocking_read(int d, buf* bufs, std::size_t count, + boost::system::error_code& ec, std::size_t& bytes_transferred); + +BOOST_ASIO_DECL std::size_t sync_write(int d, state_type state, + const buf* bufs, std::size_t count, bool all_empty, + boost::system::error_code& ec); + +BOOST_ASIO_DECL bool non_blocking_write(int d, + const buf* bufs, std::size_t count, + boost::system::error_code& ec, std::size_t& bytes_transferred); + +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, int cmd, boost::system::error_code& ec); + +BOOST_ASIO_DECL int fcntl(int d, int cmd, + long arg, boost::system::error_code& ec); + +BOOST_ASIO_DECL int poll_read(int d, + state_type state, boost::system::error_code& ec); + +BOOST_ASIO_DECL int poll_write(int d, + state_type state, boost::system::error_code& ec); + +} // namespace descriptor_ops +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include <boost/asio/detail/impl/descriptor_ops.ipp> +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) + +#endif // BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP
diff --git a/boost/boost/asio/detail/descriptor_read_op.hpp b/boost/boost/asio/detail/descriptor_read_op.hpp new file mode 100644 index 0000000..eaff8a2 --- /dev/null +++ b/boost/boost/asio/detail/descriptor_read_op.hpp
@@ -0,0 +1,121 @@ +// +// detail/descriptor_read_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP +#define BOOST_ASIO_DETAIL_DESCRIPTOR_READ_OP_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_WINDOWS) && !defined(__CYGWIN__) + +#include <boost/asio/detail/addressof.hpp> +#include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/buffer_sequence_adapter.hpp> +#include <boost/asio/detail/descriptor_ops.hpp> +#include <boost/asio/detail/fenced_block.hpp> +#include <boost/asio/detail/reactor_op.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename MutableBufferSequence> +class descriptor_read_op_base : public reactor_op +{ +public: + descriptor_read_op_base(int descriptor, + const MutableBufferSequence& buffers, func_type complete_func) + : reactor_op(&descriptor_read_op_base::do_perform, complete_func), + descriptor_(descriptor), + buffers_(buffers) + { + } + + static bool do_perform(reactor_op* base) + { + descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base)); + + buffer_sequence_adapter<boost::asio::mutable_buffer, + MutableBufferSequence> bufs(o->buffers_); + + return descriptor_ops::non_blocking_read(o->descriptor_, + bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_); + } + +private: + int descriptor_; + MutableBufferSequence buffers_; +}; + +template <typename MutableBufferSequence, typename Handler> +class descriptor_read_op + : public descriptor_read_op_base<MutableBufferSequence> +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(descriptor_read_op); + + descriptor_read_op(int descriptor, + const MutableBufferSequence& buffers, Handler& handler) + : descriptor_read_op_base<MutableBufferSequence>( + descriptor, buffers, &descriptor_read_op::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + descriptor_read_op* o(static_cast<descriptor_read_op*>(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, boost::system::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) + +#endif // BOOST_ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
diff --git a/boost/boost/asio/detail/descriptor_write_op.hpp b/boost/boost/asio/detail/descriptor_write_op.hpp new file mode 100644 index 0000000..5e6a776 --- /dev/null +++ b/boost/boost/asio/detail/descriptor_write_op.hpp
@@ -0,0 +1,121 @@ +// +// detail/descriptor_write_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP +#define BOOST_ASIO_DETAIL_DESCRIPTOR_WRITE_OP_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_WINDOWS) && !defined(__CYGWIN__) + +#include <boost/asio/detail/addressof.hpp> +#include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/buffer_sequence_adapter.hpp> +#include <boost/asio/detail/descriptor_ops.hpp> +#include <boost/asio/detail/fenced_block.hpp> +#include <boost/asio/detail/reactor_op.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename ConstBufferSequence> +class descriptor_write_op_base : public reactor_op +{ +public: + descriptor_write_op_base(int descriptor, + const ConstBufferSequence& buffers, func_type complete_func) + : reactor_op(&descriptor_write_op_base::do_perform, complete_func), + descriptor_(descriptor), + buffers_(buffers) + { + } + + static bool do_perform(reactor_op* base) + { + descriptor_write_op_base* o(static_cast<descriptor_write_op_base*>(base)); + + buffer_sequence_adapter<boost::asio::const_buffer, + ConstBufferSequence> bufs(o->buffers_); + + return descriptor_ops::non_blocking_write(o->descriptor_, + bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_); + } + +private: + int descriptor_; + ConstBufferSequence buffers_; +}; + +template <typename ConstBufferSequence, typename Handler> +class descriptor_write_op + : public descriptor_write_op_base<ConstBufferSequence> +{ +public: + BOOST_ASIO_DEFINE_HANDLER_PTR(descriptor_write_op); + + descriptor_write_op(int descriptor, + const ConstBufferSequence& buffers, Handler& handler) + : descriptor_write_op_base<ConstBufferSequence>( + descriptor, buffers, &descriptor_write_op::do_complete), + handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)) + { + } + + static void do_complete(io_service_impl* owner, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + descriptor_write_op* o(static_cast<descriptor_write_op*>(base)); + ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; + + BOOST_ASIO_HANDLER_COMPLETION((o)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, boost::system::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = boost::asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_); + BOOST_ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) + +#endif // BOOST_ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP
diff --git a/boost/boost/asio/detail/dev_poll_reactor.hpp b/boost/boost/asio/detail/dev_poll_reactor.hpp new file mode 100644 index 0000000..1b4d071 --- /dev/null +++ b/boost/boost/asio/detail/dev_poll_reactor.hpp
@@ -0,0 +1,208 @@ +// +// detail/dev_poll_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP +#define BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_DEV_POLL) + +#include <cstddef> +#include <vector> +#include <sys/devpoll.h> +#include <boost/asio/detail/hash_map.hpp> +#include <boost/asio/detail/limits.hpp> +#include <boost/asio/detail/mutex.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/reactor_op.hpp> +#include <boost/asio/detail/reactor_op_queue.hpp> +#include <boost/asio/detail/select_interrupter.hpp> +#include <boost/asio/detail/socket_types.hpp> +#include <boost/asio/detail/timer_queue_base.hpp> +#include <boost/asio/detail/timer_queue_set.hpp> +#include <boost/asio/detail/wait_op.hpp> +#include <boost/asio/io_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class dev_poll_reactor + : public boost::asio::detail::service_base<dev_poll_reactor> +{ +public: + enum op_types { read_op = 0, write_op = 1, + connect_op = 1, except_op = 2, max_ops = 3 }; + + // Per-descriptor data. + struct per_descriptor_data + { + }; + + // Constructor. + BOOST_ASIO_DECL dev_poll_reactor(boost::asio::io_service& io_service); + + // Destructor. + BOOST_ASIO_DECL ~dev_poll_reactor(); + + // Destroy all user-defined handler objects owned by the service. + BOOST_ASIO_DECL void shutdown_service(); + + // Recreate internal descriptors following a fork. + BOOST_ASIO_DECL void fork_service( + boost::asio::io_service::fork_event fork_ev); + + // Initialise the task. + BOOST_ASIO_DECL void init_task(); + + // Register a socket with the reactor. Returns 0 on success, system error + // code on failure. + BOOST_ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&); + + // Register a descriptor with an associated single operation. Returns 0 on + // success, system error code on failure. + BOOST_ASIO_DECL int register_internal_descriptor( + int op_type, socket_type descriptor, + per_descriptor_data& descriptor_data, reactor_op* op); + + // Move descriptor registration from one descriptor_data object to another. + BOOST_ASIO_DECL void move_descriptor(socket_type descriptor, + per_descriptor_data& target_descriptor_data, + per_descriptor_data& source_descriptor_data); + + // Post a reactor operation for immediate completion. + void post_immediate_completion(reactor_op* op, bool is_continuation) + { + io_service_.post_immediate_completion(op, is_continuation); + } + + // Start a new operation. The reactor operation will be performed when the + // given descriptor is flagged as ready, or an error has occurred. + BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor, + per_descriptor_data&, reactor_op* op, + bool is_continuation, bool allow_speculative); + + // Cancel all operations associated with the given descriptor. The + // handlers associated with the descriptor will be invoked with the + // operation_aborted error. + BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&); + + // Cancel any operations that are running against the descriptor and remove + // its registration from the reactor. + BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, + per_descriptor_data&, bool closing); + + // Cancel any operations that are running against the descriptor and remove + // its registration from the reactor. + BOOST_ASIO_DECL void deregister_internal_descriptor( + socket_type descriptor, per_descriptor_data&); + + // Add a new timer queue to the reactor. + template <typename Time_Traits> + void add_timer_queue(timer_queue<Time_Traits>& queue); + + // Remove a timer queue from the reactor. + template <typename Time_Traits> + void remove_timer_queue(timer_queue<Time_Traits>& queue); + + // Schedule a new operation in the given timer queue to expire at the + // specified absolute time. + template <typename Time_Traits> + void schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op); + + // Cancel the timer operations associated with the given token. Returns the + // number of operations that have been posted or dispatched. + template <typename Time_Traits> + std::size_t cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); + + // Run /dev/poll once until interrupted or events are ready to be dispatched. + BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops); + + // Interrupt the select loop. + BOOST_ASIO_DECL void interrupt(); + +private: + // Create the /dev/poll file descriptor. Throws an exception if the descriptor + // cannot be created. + BOOST_ASIO_DECL static int do_dev_poll_create(); + + // Helper function to add a new timer queue. + BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue); + + // Helper function to remove a timer queue. + BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue); + + // Get the timeout value for the /dev/poll DP_POLL operation. The timeout + // value is returned as a number of milliseconds. A return value of -1 + // indicates that the poll should block indefinitely. + BOOST_ASIO_DECL int get_timeout(); + + // Cancel all operations associated with the given descriptor. The do_cancel + // function of the handler objects will be invoked. This function does not + // acquire the dev_poll_reactor's mutex. + BOOST_ASIO_DECL void cancel_ops_unlocked(socket_type descriptor, + const boost::system::error_code& ec); + + // Add a pending event entry for the given descriptor. + BOOST_ASIO_DECL ::pollfd& add_pending_event_change(int descriptor); + + // The io_service implementation used to post completions. + io_service_impl& io_service_; + + // Mutex to protect access to internal data. + boost::asio::detail::mutex mutex_; + + // The /dev/poll file descriptor. + int dev_poll_fd_; + + // Vector of /dev/poll events waiting to be written to the descriptor. + std::vector< ::pollfd> pending_event_changes_; + + // Hash map to associate a descriptor with a pending event change index. + hash_map<int, std::size_t> pending_event_change_index_; + + // The interrupter is used to break a blocking DP_POLL operation. + select_interrupter interrupter_; + + // The queues of read, write and except operations. + reactor_op_queue<socket_type> op_queue_[max_ops]; + + // The timer queues. + timer_queue_set timer_queues_; + + // Whether the service has been shut down. + bool shutdown_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#include <boost/asio/detail/impl/dev_poll_reactor.hpp> +#if defined(BOOST_ASIO_HEADER_ONLY) +# include <boost/asio/detail/impl/dev_poll_reactor.ipp> +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_HAS_DEV_POLL) + +#endif // BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP
diff --git a/boost/boost/asio/detail/epoll_reactor.hpp b/boost/boost/asio/detail/epoll_reactor.hpp new file mode 100644 index 0000000..5b80cd9 --- /dev/null +++ b/boost/boost/asio/detail/epoll_reactor.hpp
@@ -0,0 +1,244 @@ +// +// detail/epoll_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP +#define BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if defined(BOOST_ASIO_HAS_EPOLL) + +#include <boost/asio/io_service.hpp> +#include <boost/asio/detail/atomic_count.hpp> +#include <boost/asio/detail/limits.hpp> +#include <boost/asio/detail/mutex.hpp> +#include <boost/asio/detail/object_pool.hpp> +#include <boost/asio/detail/op_queue.hpp> +#include <boost/asio/detail/reactor_op.hpp> +#include <boost/asio/detail/select_interrupter.hpp> +#include <boost/asio/detail/socket_types.hpp> +#include <boost/asio/detail/timer_queue_base.hpp> +#include <boost/asio/detail/timer_queue_set.hpp> +#include <boost/asio/detail/wait_op.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class epoll_reactor + : public boost::asio::detail::service_base<epoll_reactor> +{ +public: + enum op_types { read_op = 0, write_op = 1, + connect_op = 1, except_op = 2, max_ops = 3 }; + + // Per-descriptor queues. + class descriptor_state : operation + { + friend class epoll_reactor; + friend class object_pool_access; + + descriptor_state* next_; + descriptor_state* prev_; + + mutex mutex_; + epoll_reactor* reactor_; + int descriptor_; + uint32_t registered_events_; + op_queue<reactor_op> op_queue_[max_ops]; + bool shutdown_; + + BOOST_ASIO_DECL descriptor_state(); + void set_ready_events(uint32_t events) { task_result_ = events; } + BOOST_ASIO_DECL operation* perform_io(uint32_t events); + BOOST_ASIO_DECL static void do_complete( + io_service_impl* owner, operation* base, + const boost::system::error_code& ec, std::size_t bytes_transferred); + }; + + // Per-descriptor data. + typedef descriptor_state* per_descriptor_data; + + // Constructor. + BOOST_ASIO_DECL epoll_reactor(boost::asio::io_service& io_service); + + // Destructor. + BOOST_ASIO_DECL ~epoll_reactor(); + + // Destroy all user-defined handler objects owned by the service. + BOOST_ASIO_DECL void shutdown_service(); + + // Recreate internal descriptors following a fork. + BOOST_ASIO_DECL void fork_service( + boost::asio::io_service::fork_event fork_ev); + + // Initialise the task. + BOOST_ASIO_DECL void init_task(); + + // Register a socket with the reactor. Returns 0 on success, system error + // code on failure. + BOOST_ASIO_DECL int register_descriptor(socket_type descriptor, + per_descriptor_data& descriptor_data); + + // Register a descriptor with an associated single operation. Returns 0 on + // success, system error code on failure. + BOOST_ASIO_DECL int register_internal_descriptor( + int op_type, socket_type descriptor, + per_descriptor_data& descriptor_data, reactor_op* op); + + // Move descriptor registration from one descriptor_data object to another. + BOOST_ASIO_DECL void move_descriptor(socket_type descriptor, + per_descriptor_data& target_descriptor_data, + per_descriptor_data& source_descriptor_data); + + // Post a reactor operation for immediate completion. + void post_immediate_completion(reactor_op* op, bool is_continuation) + { + io_service_.post_immediate_completion(op, is_continuation); + } + + // Start a new operation. The reactor operation will be performed when the + // given descriptor is flagged as ready, or an error has occurred. + BOOST_ASIO_DECL void start_op(int op_type, socket_type descriptor, + per_descriptor_data& descriptor_data, reactor_op* op, + bool is_continuation, bool allow_speculative); + + // Cancel all operations associated with the given descriptor. The + // handlers associated with the descriptor will be invoked with the + // operation_aborted error. + BOOST_ASIO_DECL void cancel_ops(socket_type descriptor, + per_descriptor_data& descriptor_data); + + // Cancel any operations that are running against the descriptor and remove + // its registration from the reactor. + BOOST_ASIO_DECL void deregister_descriptor(socket_type descriptor, + per_descriptor_data& descriptor_data, bool closing); + + // Remote the descriptor's registration from the reactor. + BOOST_ASIO_DECL void deregister_internal_descriptor( + socket_type descriptor, per_descriptor_data& descriptor_data); + + // Add a new timer queue to the reactor. + template <typename Time_Traits> + void add_timer_queue(timer_queue<Time_Traits>& timer_queue); + + // Remove a timer queue from the reactor. + template <typename Time_Traits> + void remove_timer_queue(timer_queue<Time_Traits>& timer_queue); + + // Schedule a new operation in the given timer queue to expire at the + // specified absolute time. + template <typename Time_Traits> + void schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op); + + // Cancel the timer operations associated with the given token. Returns the + // number of operations that have been posted or dispatched. + template <typename Time_Traits> + std::size_t cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); + + // Run epoll once until interrupted or events are ready to be dispatched. + BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops); + + // Interrupt the select loop. + BOOST_ASIO_DECL void interrupt(); + +private: + // The hint to pass to epoll_create to size its data structures. + enum { epoll_size = 20000 }; + + // Create the epoll file descriptor. Throws an exception if the descriptor + // cannot be created. + BOOST_ASIO_DECL static int do_epoll_create(); + + // Create the timerfd file descriptor. Does not throw. + BOOST_ASIO_DECL static int do_timerfd_create(); + + // Allocate a new descriptor state object. + BOOST_ASIO_DECL descriptor_state* allocate_descriptor_state(); + + // Free an existing descriptor state object. + BOOST_ASIO_DECL void free_descriptor_state(descriptor_state* s); + + // Helper function to add a new timer queue. + BOOST_ASIO_DECL void do_add_timer_queue(timer_queue_base& queue); + + // Helper function to remove a timer queue. + BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue); + + // Called to recalculate and update the timeout. + BOOST_ASIO_DECL void update_timeout(); + + // Get the timeout value for the epoll_wait call. The timeout value is + // returned as a number of milliseconds. A return value of -1 indicates + // that epoll_wait should block indefinitely. + BOOST_ASIO_DECL int get_timeout(); + +#if defined(BOOST_ASIO_HAS_TIMERFD) + // Get the timeout value for the timer descriptor. The return value is the + // flag argument to be used when calling timerfd_settime. + BOOST_ASIO_DECL int get_timeout(itimerspec& ts); +#endif // defined(BOOST_ASIO_HAS_TIMERFD) + + // The io_service implementation used to post completions. + io_service_impl& io_service_; + + // Mutex to protect access to internal data. + mutex mutex_; + + // The interrupter is used to break a blocking epoll_wait call. + select_interrupter interrupter_; + + // The epoll file descriptor. + int epoll_fd_; + + // The timer file descriptor. + int timer_fd_; + + // The timer queues. + timer_queue_set timer_queues_; + + // Whether the service has been shut down. + bool shutdown_; + + // Mutex to protect access to the registered descriptors. + mutex registered_descriptors_mutex_; + + // Keep track of all registered descriptors. + object_pool<descriptor_state> registered_descriptors_; + + // Helper class to do post-perform_io cleanup. + struct perform_io_cleanup_on_block_exit; + friend struct perform_io_cleanup_on_block_exit; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#include <boost/asio/detail/impl/epoll_reactor.hpp> +#if defined(BOOST_ASIO_HEADER_ONLY) +# include <boost/asio/detail/impl/epoll_reactor.ipp> +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_HAS_EPOLL) + +#endif // BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP
diff --git a/boost/boost/asio/detail/event.hpp b/boost/boost/asio/detail/event.hpp new file mode 100644 index 0000000..e6cf2c3 --- /dev/null +++ b/boost/boost/asio/detail/event.hpp
@@ -0,0 +1,50 @@ +// +// detail/event.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_EVENT_HPP +#define BOOST_ASIO_DETAIL_EVENT_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_HAS_THREADS) +# include <boost/asio/detail/null_event.hpp> +#elif defined(BOOST_ASIO_WINDOWS) +# include <boost/asio/detail/win_event.hpp> +#elif defined(BOOST_ASIO_HAS_PTHREADS) +# include <boost/asio/detail/posix_event.hpp> +#elif defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +# include <boost/asio/detail/std_event.hpp> +#else +# error Only Windows, POSIX and std::condition_variable are supported! +#endif + +namespace boost { +namespace asio { +namespace detail { + +#if !defined(BOOST_ASIO_HAS_THREADS) +typedef null_event event; +#elif defined(BOOST_ASIO_WINDOWS) +typedef win_event event; +#elif defined(BOOST_ASIO_HAS_PTHREADS) +typedef posix_event event; +#elif defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR) +typedef std_event event; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_EVENT_HPP
diff --git a/boost/boost/asio/detail/eventfd_select_interrupter.hpp b/boost/boost/asio/detail/eventfd_select_interrupter.hpp new file mode 100644 index 0000000..d0d38b6 --- /dev/null +++ b/boost/boost/asio/detail/eventfd_select_interrupter.hpp
@@ -0,0 +1,85 @@ +// +// detail/eventfd_select_interrupter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail 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_EVENTFD_SELECT_INTERRUPTER_HPP +#define BOOST_ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_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_EVENTFD) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class eventfd_select_interrupter +{ +public: + // Constructor. + BOOST_ASIO_DECL eventfd_select_interrupter(); + + // Destructor. + BOOST_ASIO_DECL ~eventfd_select_interrupter(); + + // Recreate the interrupter's descriptors. Used after a fork. + BOOST_ASIO_DECL void recreate(); + + // Interrupt the select call. + BOOST_ASIO_DECL void interrupt(); + + // Reset the select interrupt. Returns true if the call was interrupted. + BOOST_ASIO_DECL bool reset(); + + // Get the read descriptor to be passed to select. + int read_descriptor() const + { + return read_descriptor_; + } + +private: + // Open the descriptors. Throws on error. + BOOST_ASIO_DECL void open_descriptors(); + + // Close the descriptors. + BOOST_ASIO_DECL void close_descriptors(); + + // The read end of a connection used to interrupt the select call. This file + // descriptor is passed to select such that when it is time to stop, a single + // 64bit value will be written on the other end of the connection and this + // descriptor will become readable. + int read_descriptor_; + + // The write end of a connection used to interrupt the select call. A single + // 64bit non-zero value may be written to this to wake up the select which is + // waiting for the other end to become readable. This descriptor will only + // differ from the read descriptor when a pipe is used. + int write_descriptor_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include <boost/asio/detail/impl/eventfd_select_interrupter.ipp> +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // defined(BOOST_ASIO_HAS_EVENTFD) + +#endif // BOOST_ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP
diff --git a/boost/boost/asio/detail/fd_set_adapter.hpp b/boost/boost/asio/detail/fd_set_adapter.hpp new file mode 100644 index 0000000..0a28dc4 --- /dev/null +++ b/boost/boost/asio/detail/fd_set_adapter.hpp
@@ -0,0 +1,41 @@ +// +// detail/fd_set_adapter.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP +#define BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include <boost/asio/detail/posix_fd_set_adapter.hpp> +#include <boost/asio/detail/win_fd_set_adapter.hpp> + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +typedef win_fd_set_adapter fd_set_adapter; +#else +typedef posix_fd_set_adapter fd_set_adapter; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP
diff --git a/boost/boost/asio/detail/fenced_block.hpp b/boost/boost/asio/detail/fenced_block.hpp new file mode 100644 index 0000000..ea30c65 --- /dev/null +++ b/boost/boost/asio/detail/fenced_block.hpp
@@ -0,0 +1,78 @@ +// +// detail/fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_FENCED_BLOCK_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_THREADS) \ + || defined(BOOST_ASIO_DISABLE_FENCED_BLOCK) +# include <boost/asio/detail/null_fenced_block.hpp> +#elif defined(__MACH__) && defined(__APPLE__) +# 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(__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> +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +# include <boost/asio/detail/gcc_x86_fenced_block.hpp> +#elif defined(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ + && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) +# include <boost/asio/detail/gcc_sync_fenced_block.hpp> +#elif defined(BOOST_ASIO_WINDOWS) && !defined(UNDER_CE) +# include <boost/asio/detail/win_fenced_block.hpp> +#else +# include <boost/asio/detail/null_fenced_block.hpp> +#endif + +namespace boost { +namespace asio { +namespace detail { + +#if !defined(BOOST_ASIO_HAS_THREADS) \ + || defined(BOOST_ASIO_DISABLE_FENCED_BLOCK) +typedef null_fenced_block fenced_block; +#elif defined(__MACH__) && defined(__APPLE__) +typedef macos_fenced_block fenced_block; +#elif defined(__sun) +typedef solaris_fenced_block fenced_block; +#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; +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +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__) +typedef gcc_sync_fenced_block fenced_block; +#elif defined(BOOST_ASIO_WINDOWS) && !defined(UNDER_CE) +typedef win_fenced_block fenced_block; +#else +typedef null_fenced_block fenced_block; +#endif + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_FENCED_BLOCK_HPP
diff --git a/boost/boost/asio/detail/function.hpp b/boost/boost/asio/detail/function.hpp new file mode 100644 index 0000000..191615b --- /dev/null +++ b/boost/boost/asio/detail/function.hpp
@@ -0,0 +1,40 @@ +// +// detail/function.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_FUNCTION_HPP +#define BOOST_ASIO_DETAIL_FUNCTION_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_STD_FUNCTION) +# include <functional> +#else // defined(BOOST_ASIO_HAS_STD_FUNCTION) +# include <boost/function.hpp> +#endif // defined(BOOST_ASIO_HAS_STD_FUNCTION) + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_HAS_STD_FUNCTION) +using std::function; +#else // defined(BOOST_ASIO_HAS_STD_FUNCTION) +using boost::function; +#endif // defined(BOOST_ASIO_HAS_STD_FUNCTION) + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_FUNCTION_HPP
diff --git a/boost/boost/asio/detail/gcc_arm_fenced_block.hpp b/boost/boost/asio/detail/gcc_arm_fenced_block.hpp new file mode 100644 index 0000000..c1b3348 --- /dev/null +++ b/boost/boost/asio/detail/gcc_arm_fenced_block.hpp
@@ -0,0 +1,91 @@ +// +// detail/gcc_arm_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_GCC_ARM_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_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(__GNUC__) && defined(__arm__) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class gcc_arm_fenced_block + : private noncopyable +{ +public: + enum half_t { half }; + enum full_t { full }; + + // Constructor for a half fenced block. + explicit gcc_arm_fenced_block(half_t) + { + } + + // Constructor for a full fenced block. + explicit gcc_arm_fenced_block(full_t) + { + barrier(); + } + + // Destructor. + ~gcc_arm_fenced_block() + { + barrier(); + } + +private: + static void barrier() + { +#if defined(__ARM_ARCH_4__) \ + || defined(__ARM_ARCH_4T__) \ + || defined(__ARM_ARCH_5__) \ + || defined(__ARM_ARCH_5E__) \ + || defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) \ + || defined(__ARM_ARCH_6__) \ + || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6T2__) +# if defined(__thumb__) + // This is just a placeholder and almost certainly not sufficient. + __asm__ __volatile__ ("" : : : "memory"); +# else // defined(__thumb__) + int a = 0, b = 0; + __asm__ __volatile__ ("swp %0, %1, [%2]" + : "=&r"(a) : "r"(1), "r"(&b) : "memory", "cc"); +# endif // defined(__thumb__) +#else + // ARMv7 and later. + __asm__ __volatile__ ("dmb" : : : "memory"); +#endif + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(__GNUC__) && defined(__arm__) + +#endif // BOOST_ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
diff --git a/boost/boost/asio/detail/gcc_hppa_fenced_block.hpp b/boost/boost/asio/detail/gcc_hppa_fenced_block.hpp new file mode 100644 index 0000000..9f3a0bb --- /dev/null +++ b/boost/boost/asio/detail/gcc_hppa_fenced_block.hpp
@@ -0,0 +1,68 @@ +// +// detail/gcc_hppa_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_GCC_HPPA_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_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(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class gcc_hppa_fenced_block + : private noncopyable +{ +public: + enum half_t { half }; + enum full_t { full }; + + // Constructor for a half fenced block. + explicit gcc_hppa_fenced_block(half_t) + { + } + + // Constructor for a full fenced block. + explicit gcc_hppa_fenced_block(full_t) + { + barrier(); + } + + // Destructor. + ~gcc_hppa_fenced_block() + { + barrier(); + } + +private: + static void barrier() + { + // This is just a placeholder and almost certainly not sufficient. + __asm__ __volatile__ ("" : : : "memory"); + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) + +#endif // BOOST_ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
diff --git a/boost/boost/asio/detail/gcc_sync_fenced_block.hpp b/boost/boost/asio/detail/gcc_sync_fenced_block.hpp new file mode 100644 index 0000000..570f7ea --- /dev/null +++ b/boost/boost/asio/detail/gcc_sync_fenced_block.hpp
@@ -0,0 +1,65 @@ +// +// detail/gcc_sync_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_GCC_SYNC_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_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(__GNUC__) \ + && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ + && !defined(__INTEL_COMPILER) && !defined(__ICL) \ + && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class gcc_sync_fenced_block + : private noncopyable +{ +public: + enum half_or_full_t { half, full }; + + // Constructor. + explicit gcc_sync_fenced_block(half_or_full_t) + : value_(0) + { + __sync_lock_test_and_set(&value_, 1); + } + + // Destructor. + ~gcc_sync_fenced_block() + { + __sync_lock_release(&value_); + } + +private: + int value_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(__GNUC__) + // && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) + // && !defined(__INTEL_COMPILER) && !defined(__ICL) + // && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) + +#endif // BOOST_ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP
diff --git a/boost/boost/asio/detail/gcc_x86_fenced_block.hpp b/boost/boost/asio/detail/gcc_x86_fenced_block.hpp new file mode 100644 index 0000000..81d5179 --- /dev/null +++ b/boost/boost/asio/detail/gcc_x86_fenced_block.hpp
@@ -0,0 +1,99 @@ +// +// detail/gcc_x86_fenced_block.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_GCC_X86_FENCED_BLOCK_HPP +#define BOOST_ASIO_DETAIL_GCC_X86_FENCED_BLOCK_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(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class gcc_x86_fenced_block + : private noncopyable +{ +public: + enum half_t { half }; + enum full_t { full }; + + // Constructor for a half fenced block. + explicit gcc_x86_fenced_block(half_t) + { + } + + // Constructor for a full fenced block. + explicit gcc_x86_fenced_block(full_t) + { + lbarrier(); + } + + // Destructor. + ~gcc_x86_fenced_block() + { + sbarrier(); + } + +private: + static int barrier() + { + int r = 0, m = 1; + __asm__ __volatile__ ( + "xchgl %0, %1" : + "=r"(r), "=m"(m) : + "0"(1), "m"(m) : + "memory", "cc"); + return r; + } + + static void lbarrier() + { +#if defined(__SSE2__) +# if (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) + __builtin_ia32_lfence(); +# else // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) + __asm__ __volatile__ ("lfence" ::: "memory"); +# endif // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) +#else // defined(__SSE2__) + barrier(); +#endif // defined(__SSE2__) + } + + static void sbarrier() + { +#if defined(__SSE2__) +# if (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) + __builtin_ia32_sfence(); +# else // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) + __asm__ __volatile__ ("sfence" ::: "memory"); +# endif // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) +#else // defined(__SSE2__) + barrier(); +#endif // defined(__SSE2__) + } +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +#endif // BOOST_ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP
diff --git a/boost/boost/asio/detail/handler_alloc_helpers.hpp b/boost/boost/asio/detail/handler_alloc_helpers.hpp new file mode 100644 index 0000000..a602d8e --- /dev/null +++ b/boost/boost/asio/detail/handler_alloc_helpers.hpp
@@ -0,0 +1,82 @@ +// +// detail/handler_alloc_helpers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP +#define BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/addressof.hpp> +#include <boost/asio/detail/noncopyable.hpp> +#include <boost/asio/handler_alloc_hook.hpp> + +#include <boost/asio/detail/push_options.hpp> + +// Calls to asio_handler_allocate and asio_handler_deallocate must be made from +// a namespace that does not contain any overloads of these functions. The +// boost_asio_handler_alloc_helpers namespace is defined here for that purpose. +namespace boost_asio_handler_alloc_helpers { + +template <typename Handler> +inline void* allocate(std::size_t s, Handler& h) +{ +#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS) + return ::operator new(s); +#else + using boost::asio::asio_handler_allocate; + return asio_handler_allocate(s, boost::asio::detail::addressof(h)); +#endif +} + +template <typename Handler> +inline void deallocate(void* p, std::size_t s, Handler& h) +{ +#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS) + ::operator delete(p); +#else + using boost::asio::asio_handler_deallocate; + asio_handler_deallocate(p, s, boost::asio::detail::addressof(h)); +#endif +} + +} // namespace boost_asio_handler_alloc_helpers + +#define BOOST_ASIO_DEFINE_HANDLER_PTR(op) \ + struct ptr \ + { \ + Handler* h; \ + void* v; \ + op* p; \ + ~ptr() \ + { \ + reset(); \ + } \ + void reset() \ + { \ + if (p) \ + { \ + p->~op(); \ + p = 0; \ + } \ + if (v) \ + { \ + boost_asio_handler_alloc_helpers::deallocate(v, sizeof(op), *h); \ + v = 0; \ + } \ + } \ + } \ + /**/ + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
diff --git a/boost/boost/asio/detail/handler_cont_helpers.hpp b/boost/boost/asio/detail/handler_cont_helpers.hpp new file mode 100644 index 0000000..ec3abb7 --- /dev/null +++ b/boost/boost/asio/detail/handler_cont_helpers.hpp
@@ -0,0 +1,45 @@ +// +// detail/handler_cont_helpers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP +#define BOOST_ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP + +#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/addressof.hpp> +#include <boost/asio/handler_continuation_hook.hpp> + +#include <boost/asio/detail/push_options.hpp> + +// Calls to asio_handler_is_continuation must be made from a namespace that +// does not contain overloads of this function. This namespace is defined here +// for that purpose. +namespace boost_asio_handler_cont_helpers { + +template <typename Context> +inline bool is_continuation(Context& context) +{ +#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS) + return false; +#else + using boost::asio::asio_handler_is_continuation; + return asio_handler_is_continuation( + boost::asio::detail::addressof(context)); +#endif +} + +} // namespace boost_asio_handler_cont_helpers + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP
diff --git a/boost/boost/asio/detail/handler_invoke_helpers.hpp b/boost/boost/asio/detail/handler_invoke_helpers.hpp new file mode 100644 index 0000000..fed4c4e --- /dev/null +++ b/boost/boost/asio/detail/handler_invoke_helpers.hpp
@@ -0,0 +1,57 @@ +// +// detail/handler_invoke_helpers.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP +#define BOOST_ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <boost/asio/detail/addressof.hpp> +#include <boost/asio/handler_invoke_hook.hpp> + +#include <boost/asio/detail/push_options.hpp> + +// Calls to asio_handler_invoke must be made from a namespace that does not +// contain overloads of this function. The boost_asio_handler_invoke_helpers +// namespace is defined here for that purpose. +namespace boost_asio_handler_invoke_helpers { + +template <typename Function, typename Context> +inline void invoke(Function& function, Context& context) +{ +#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS) + Function tmp(function); + tmp(); +#else + using boost::asio::asio_handler_invoke; + asio_handler_invoke(function, boost::asio::detail::addressof(context)); +#endif +} + +template <typename Function, typename Context> +inline void invoke(const Function& function, Context& context) +{ +#if !defined(BOOST_ASIO_HAS_HANDLER_HOOKS) + Function tmp(function); + tmp(); +#else + using boost::asio::asio_handler_invoke; + asio_handler_invoke(function, boost::asio::detail::addressof(context)); +#endif +} + +} // namespace boost_asio_handler_invoke_helpers + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
diff --git a/boost/boost/asio/detail/handler_tracking.hpp b/boost/boost/asio/detail/handler_tracking.hpp new file mode 100644 index 0000000..f1a89fe --- /dev/null +++ b/boost/boost/asio/detail/handler_tracking.hpp
@@ -0,0 +1,161 @@ +// +// detail/handler_tracking.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_TRACKING_HPP +#define BOOST_ASIO_DETAIL_HANDLER_TRACKING_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_ENABLE_HANDLER_TRACKING) +# include <boost/system/error_code.hpp> +# include <boost/asio/detail/cstdint.hpp> +# include <boost/asio/detail/static_mutex.hpp> +# include <boost/asio/detail/tss_ptr.hpp> +#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING) + +class handler_tracking +{ +public: + class completion; + + // Base class for objects containing tracked handlers. + class tracked_handler + { + private: + // Only the handler_tracking class will have access to the id. + friend class handler_tracking; + friend class completion; + uint64_t id_; + + protected: + // Constructor initialises with no id. + tracked_handler() : id_(0) {} + + // Prevent deletion through this type. + ~tracked_handler() {} + }; + + // Initialise the tracking system. + BOOST_ASIO_DECL static void init(); + + // Record the creation of a tracked handler. + BOOST_ASIO_DECL static void creation(tracked_handler* h, + const char* object_type, void* object, const char* op_name); + + class completion + { + public: + // Constructor records that handler is to be invoked with no arguments. + BOOST_ASIO_DECL explicit completion(tracked_handler* h); + + // Destructor records only when an exception is thrown from the handler, or + // if the memory is being freed without the handler having been invoked. + BOOST_ASIO_DECL ~completion(); + + // Records that handler is to be invoked with no arguments. + BOOST_ASIO_DECL void invocation_begin(); + + // Records that handler is to be invoked with one arguments. + BOOST_ASIO_DECL void invocation_begin(const boost::system::error_code& ec); + + // Constructor records that handler is to be invoked with two arguments. + BOOST_ASIO_DECL void invocation_begin( + const boost::system::error_code& ec, std::size_t bytes_transferred); + + // Constructor records that handler is to be invoked with two arguments. + BOOST_ASIO_DECL void invocation_begin( + const boost::system::error_code& ec, int signal_number); + + // Constructor records that handler is to be invoked with two arguments. + BOOST_ASIO_DECL void invocation_begin( + const boost::system::error_code& ec, const char* arg); + + // Record that handler invocation has ended. + BOOST_ASIO_DECL void invocation_end(); + + private: + friend class handler_tracking; + uint64_t id_; + bool invoked_; + completion* next_; + }; + + // Record an operation that affects pending handlers. + BOOST_ASIO_DECL static void operation(const char* object_type, + void* object, const char* op_name); + + // Write a line of output. + BOOST_ASIO_DECL static void write_line(const char* format, ...); + +private: + struct tracking_state; + BOOST_ASIO_DECL static tracking_state* get_state(); +}; + +# define BOOST_ASIO_INHERIT_TRACKED_HANDLER \ + : public boost::asio::detail::handler_tracking::tracked_handler + +# define BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER \ + , public boost::asio::detail::handler_tracking::tracked_handler + +# define BOOST_ASIO_HANDLER_TRACKING_INIT \ + boost::asio::detail::handler_tracking::init() + +# define BOOST_ASIO_HANDLER_CREATION(args) \ + boost::asio::detail::handler_tracking::creation args + +# define BOOST_ASIO_HANDLER_COMPLETION(args) \ + boost::asio::detail::handler_tracking::completion tracked_completion args + +# define BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) \ + tracked_completion.invocation_begin args + +# define BOOST_ASIO_HANDLER_INVOCATION_END \ + tracked_completion.invocation_end() + +# define BOOST_ASIO_HANDLER_OPERATION(args) \ + boost::asio::detail::handler_tracking::operation args + +#else // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING) + +# define BOOST_ASIO_INHERIT_TRACKED_HANDLER +# define BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER +# define BOOST_ASIO_HANDLER_TRACKING_INIT (void)0 +# define BOOST_ASIO_HANDLER_CREATION(args) (void)0 +# define BOOST_ASIO_HANDLER_COMPLETION(args) (void)0 +# define BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) (void)0 +# define BOOST_ASIO_HANDLER_INVOCATION_END (void)0 +# define BOOST_ASIO_HANDLER_OPERATION(args) (void)0 + +#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING) + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#if defined(BOOST_ASIO_HEADER_ONLY) +# include <boost/asio/detail/impl/handler_tracking.ipp> +#endif // defined(BOOST_ASIO_HEADER_ONLY) + +#endif // BOOST_ASIO_DETAIL_HANDLER_TRACKING_HPP
diff --git a/boost/boost/asio/detail/handler_type_requirements.hpp b/boost/boost/asio/detail/handler_type_requirements.hpp new file mode 100644 index 0000000..a2d3fd1 --- /dev/null +++ b/boost/boost/asio/detail/handler_type_requirements.hpp
@@ -0,0 +1,490 @@ +// +// detail/handler_type_requirements.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP +#define BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +// Older versions of gcc have difficulty compiling the sizeof expressions where +// we test the handler type requirements. We'll disable checking of handler type +// requirements for those compilers, but otherwise enable it by default. +#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) +# if !defined(__GNUC__) || (__GNUC__ >= 4) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1 +# endif // !defined(__GNUC__) || (__GNUC__ >= 4) +#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) + +// With C++0x we can use a combination of enhanced SFINAE and static_assert to +// generate better template error messages. As this technique is not yet widely +// portable, we'll only enable it for tested compilers. +#if !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) +# if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# endif // defined(__GNUC__) +# if defined(BOOST_ASIO_MSVC) +# if (_MSC_VER >= 1600) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // (_MSC_VER >= 1600) +# endif // defined(BOOST_ASIO_MSVC) +# if defined(__clang__) +# if __has_feature(__cxx_static_assert__) +# define BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1 +# endif // __has_feature(cxx_static_assert) +# endif // defined(__clang__) +#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS) + +#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) +# include <boost/asio/handler_type.hpp> +#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +// Newer gcc needs special treatment to suppress unused typedef warnings. +#if defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) +# define BOOST_ASIO_UNUSED_TYPEDEF __attribute__((__unused__)) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) +#endif // defined(__GNUC__) +#if !defined(BOOST_ASIO_UNUSED_TYPEDEF) +# define BOOST_ASIO_UNUSED_TYPEDEF +#endif // !defined(BOOST_ASIO_UNUSED_TYPEDEF) + +namespace boost { +namespace asio { +namespace detail { + +#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +template <typename Handler> +auto zero_arg_handler_test(Handler h, void*) + -> decltype( + sizeof(Handler(static_cast<const Handler&>(h))), + ((h)()), + char(0)); + +template <typename Handler> +char (&zero_arg_handler_test(Handler, ...))[2]; + +template <typename Handler, typename Arg1> +auto one_arg_handler_test(Handler h, Arg1* a1) + -> decltype( + sizeof(Handler(static_cast<const Handler&>(h))), + ((h)(*a1)), + char(0)); + +template <typename Handler> +char (&one_arg_handler_test(Handler h, ...))[2]; + +template <typename Handler, typename Arg1, typename Arg2> +auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) + -> decltype( + sizeof(Handler(static_cast<const Handler&>(h))), + ((h)(*a1, *a2)), + char(0)); + +template <typename Handler> +char (&two_arg_handler_test(Handler, ...))[2]; + +# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \ + static_assert(expr, msg); + +# else // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) + +# endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT) + +template <typename T> T& lvref(); +template <typename T> T& lvref(T); +template <typename T> const T& clvref(); +template <typename T> const T& clvref(T); +template <typename T> char argbyv(T); + +template <int> +struct handler_type_requirements +{ +}; + +#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void()) asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::zero_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), 0)) == 1, \ + "CompletionHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()(), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_READ_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, std::size_t)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0), \ + static_cast<const std::size_t*>(0))) == 1, \ + "ReadHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>(), \ + boost::asio::detail::lvref<const std::size_t>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + + +#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, std::size_t)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0), \ + static_cast<const std::size_t*>(0))) == 1, \ + "WriteHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>(), \ + boost::asio::detail::lvref<const std::size_t>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0))) == 1, \ + "AcceptHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0))) == 1, \ + "ConnectHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, iter_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0), \ + static_cast<const iter_type*>(0))) == 1, \ + "ComposedConnectHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>(), \ + boost::asio::detail::lvref<const iter_type>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, iter_type)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0), \ + static_cast<const iter_type*>(0))) == 1, \ + "ResolveHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>(), \ + boost::asio::detail::lvref<const iter_type>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0))) == 1, \ + "WaitHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, int)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0), \ + static_cast<const int*>(0))) == 1, \ + "SignalHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>(), \ + boost::asio::detail::lvref<const int>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0))) == 1, \ + "HandshakeHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code, std::size_t)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::two_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0), \ + static_cast<const std::size_t*>(0))) == 1, \ + "BufferedHandshakeHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>(), \ + boost::asio::detail::lvref<const std::size_t>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ + handler_type, handler) \ + \ + typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \ + void(boost::system::error_code)) \ + asio_true_handler_type; \ + \ + BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \ + sizeof(boost::asio::detail::one_arg_handler_test( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>(), \ + static_cast<const boost::system::error_code*>(0))) == 1, \ + "ShutdownHandler type requirements not met") \ + \ + typedef boost::asio::detail::handler_type_requirements< \ + sizeof( \ + boost::asio::detail::argbyv( \ + boost::asio::detail::clvref< \ + asio_true_handler_type>())) + \ + sizeof( \ + boost::asio::detail::lvref< \ + asio_true_handler_type>()( \ + boost::asio::detail::lvref<const boost::system::error_code>()), \ + char(0))> BOOST_ASIO_UNUSED_TYPEDEF + +#else // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +#define BOOST_ASIO_COMPLETION_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_READ_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WRITE_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_ACCEPT_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \ + handler_type, handler, iter_type) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_WAIT_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SIGNAL_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#define BOOST_ASIO_SHUTDOWN_HANDLER_CHECK( \ + handler_type, handler) \ + typedef int BOOST_ASIO_UNUSED_TYPEDEF + +#endif // !defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS) + +} // namespace detail +} // namespace asio +} // namespace boost + +#endif // BOOST_ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP
diff --git a/boost/boost/asio/detail/hash_map.hpp b/boost/boost/asio/detail/hash_map.hpp new file mode 100644 index 0000000..20b3332 --- /dev/null +++ b/boost/boost/asio/detail/hash_map.hpp
@@ -0,0 +1,333 @@ +// +// detail/hash_map.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_HASH_MAP_HPP +#define BOOST_ASIO_DETAIL_HASH_MAP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <list> +#include <utility> +#include <boost/asio/detail/assert.hpp> +#include <boost/asio/detail/noncopyable.hpp> + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +# include <boost/asio/detail/socket_types.hpp> +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +inline std::size_t calculate_hash_value(int i) +{ + return static_cast<std::size_t>(i); +} + +inline std::size_t calculate_hash_value(void* p) +{ + return reinterpret_cast<std::size_t>(p) + + (reinterpret_cast<std::size_t>(p) >> 3); +} + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +inline std::size_t calculate_hash_value(SOCKET s) +{ + return static_cast<std::size_t>(s); +} +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + +// Note: assumes K and V are POD types. +template <typename K, typename V> +class hash_map + : private noncopyable +{ +public: + // The type of a value in the map. + typedef std::pair<K, V> value_type; + + // The type of a non-const iterator over the hash map. + typedef typename std::list<value_type>::iterator iterator; + + // The type of a const iterator over the hash map. + typedef typename std::list<value_type>::const_iterator const_iterator; + + // Constructor. + hash_map() + : size_(0), + buckets_(0), + num_buckets_(0) + { + } + + // Destructor. + ~hash_map() + { + delete[] buckets_; + } + + // Get an iterator for the beginning of the map. + iterator begin() + { + return values_.begin(); + } + + // Get an iterator for the beginning of the map. + const_iterator begin() const + { + return values_.begin(); + } + + // Get an iterator for the end of the map. + iterator end() + { + return values_.end(); + } + + // Get an iterator for the end of the map. + const_iterator end() const + { + return values_.end(); + } + + // Check whether the map is empty. + bool empty() const + { + return values_.empty(); + } + + // Find an entry in the map. + iterator find(const K& k) + { + if (num_buckets_) + { + size_t bucket = calculate_hash_value(k) % num_buckets_; + iterator it = buckets_[bucket].first; + if (it == values_.end()) + return values_.end(); + iterator end_it = buckets_[bucket].last; + ++end_it; + while (it != end_it) + { + if (it->first == k) + return it; + ++it; + } + } + return values_.end(); + } + + // Find an entry in the map. + const_iterator find(const K& k) const + { + if (num_buckets_) + { + size_t bucket = calculate_hash_value(k) % num_buckets_; + const_iterator it = buckets_[bucket].first; + if (it == values_.end()) + return it; + const_iterator end_it = buckets_[bucket].last; + ++end_it; + while (it != end_it) + { + if (it->first == k) + return it; + ++it; + } + } + return values_.end(); + } + + // Insert a new entry into the map. + std::pair<iterator, bool> insert(const value_type& v) + { + if (size_ + 1 >= num_buckets_) + rehash(hash_size(size_ + 1)); + size_t bucket = calculate_hash_value(v.first) % num_buckets_; + iterator it = buckets_[bucket].first; + if (it == values_.end()) + { + buckets_[bucket].first = buckets_[bucket].last = + values_insert(values_.end(), v); + ++size_; + return std::pair<iterator, bool>(buckets_[bucket].last, true); + } + iterator end_it = buckets_[bucket].last; + ++end_it; + while (it != end_it) + { + if (it->first == v.first) + return std::pair<iterator, bool>(it, false); + ++it; + } + buckets_[bucket].last = values_insert(end_it, v); + ++size_; + return std::pair<iterator, bool>(buckets_[bucket].last, true); + } + + // Erase an entry from the map. + void erase(iterator it) + { + BOOST_ASIO_ASSERT(it != values_.end()); + BOOST_ASIO_ASSERT(num_buckets_ != 0); + + size_t bucket = calculate_hash_value(it->first) % num_buckets_; + bool is_first = (it == buckets_[bucket].first); + bool is_last = (it == buckets_[bucket].last); + if (is_first && is_last) + buckets_[bucket].first = buckets_[bucket].last = values_.end(); + else if (is_first) + ++buckets_[bucket].first; + else if (is_last) + --buckets_[bucket].last; + + values_erase(it); + --size_; + } + + // Erase a key from the map. + void erase(const K& k) + { + iterator it = find(k); + if (it != values_.end()) + erase(it); + } + + // Remove all entries from the map. + void clear() + { + // Clear the values. + values_.clear(); + size_ = 0; + + // Initialise all buckets to empty. + iterator end_it = values_.end(); + for (size_t i = 0; i < num_buckets_; ++i) + buckets_[i].first = buckets_[i].last = end_it; + } + +private: + // Calculate the hash size for the specified number of elements. + static std::size_t hash_size(std::size_t num_elems) + { + static std::size_t sizes[] = + { +#if defined(BOOST_ASIO_HASH_MAP_BUCKETS) + BOOST_ASIO_HASH_MAP_BUCKETS +#else // BOOST_ASIO_HASH_MAP_BUCKETS + 3, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593, + 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, + 12582917, 25165843 +#endif // BOOST_ASIO_HASH_MAP_BUCKETS + }; + const std::size_t nth_size = sizeof(sizes) / sizeof(std::size_t) - 1; + for (std::size_t i = 0; i < nth_size; ++i) + if (num_elems < sizes[i]) + return sizes[i]; + return sizes[nth_size]; + } + + // Re-initialise the hash from the values already contained in the list. + void rehash(std::size_t num_buckets) + { + if (num_buckets == num_buckets_) + return; + num_buckets_ = num_buckets; + BOOST_ASIO_ASSERT(num_buckets_ != 0); + + iterator end_iter = values_.end(); + + // Update number of buckets and initialise all buckets to empty. + bucket_type* tmp = new bucket_type[num_buckets_]; + delete[] buckets_; + buckets_ = tmp; + for (std::size_t i = 0; i < num_buckets_; ++i) + buckets_[i].first = buckets_[i].last = end_iter; + + // Put all values back into the hash. + iterator iter = values_.begin(); + while (iter != end_iter) + { + std::size_t bucket = calculate_hash_value(iter->first) % num_buckets_; + if (buckets_[bucket].last == end_iter) + { + buckets_[bucket].first = buckets_[bucket].last = iter++; + } + else if (++buckets_[bucket].last == iter) + { + ++iter; + } + else + { + values_.splice(buckets_[bucket].last, values_, iter++); + --buckets_[bucket].last; + } + } + } + + // Insert an element into the values list by splicing from the spares list, + // if a spare is available, and otherwise by inserting a new element. + iterator values_insert(iterator it, const value_type& v) + { + if (spares_.empty()) + { + return values_.insert(it, v); + } + else + { + spares_.front() = v; + values_.splice(it, spares_, spares_.begin()); + return --it; + } + } + + // Erase an element from the values list by splicing it to the spares list. + void values_erase(iterator it) + { + *it = value_type(); + spares_.splice(spares_.begin(), values_, it); + } + + // The number of elements in the hash. + std::size_t size_; + + // The list of all values in the hash map. + std::list<value_type> values_; + + // The list of spare nodes waiting to be recycled. Assumes that POD types only + // are stored in the hash map. + std::list<value_type> spares_; + + // The type for a bucket in the hash table. + struct bucket_type + { + iterator first; + iterator last; + }; + + // The buckets in the hash. + bucket_type* buckets_; + + // The number of buckets in the hash. + std::size_t num_buckets_; +}; + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_HASH_MAP_HPP
diff --git a/boost/boost/asio/detail/impl/buffer_sequence_adapter.ipp b/boost/boost/asio/detail/impl/buffer_sequence_adapter.ipp new file mode 100644 index 0000000..c5a1f3d --- /dev/null +++ b/boost/boost/asio/detail/impl/buffer_sequence_adapter.ipp
@@ -0,0 +1,120 @@ +// +// detail/impl/buffer_sequence_adapter.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_BUFFER_SEQUENCE_ADAPTER_IPP +#define BOOST_ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_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_WINDOWS_RUNTIME) + +#include <robuffer.h> +#include <windows.storage.streams.h> +#include <wrl/implements.h> +#include <boost/asio/detail/buffer_sequence_adapter.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class winrt_buffer_impl : + public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags< + Microsoft::WRL::RuntimeClassType::WinRtClassicComMix>, + ABI::Windows::Storage::Streams::IBuffer, + Windows::Storage::Streams::IBufferByteAccess> +{ +public: + explicit winrt_buffer_impl(const boost::asio::const_buffer& b) + { + bytes_ = const_cast<byte*>(boost::asio::buffer_cast<const byte*>(b)); + length_ = boost::asio::buffer_size(b); + capacity_ = boost::asio::buffer_size(b); + } + + explicit winrt_buffer_impl(const boost::asio::mutable_buffer& b) + { + bytes_ = const_cast<byte*>(boost::asio::buffer_cast<const byte*>(b)); + length_ = 0; + capacity_ = boost::asio::buffer_size(b); + } + + ~winrt_buffer_impl() + { + } + + STDMETHODIMP Buffer(byte** value) + { + *value = bytes_; + return S_OK; + } + + STDMETHODIMP get_Capacity(UINT32* value) + { + *value = capacity_; + return S_OK; + } + + STDMETHODIMP get_Length(UINT32 *value) + { + *value = length_; + return S_OK; + } + + STDMETHODIMP put_Length(UINT32 value) + { + if (value > capacity_) + return E_INVALIDARG; + length_ = value; + return S_OK; + } + +private: + byte* bytes_; + UINT32 length_; + UINT32 capacity_; +}; + +void buffer_sequence_adapter_base::init_native_buffer( + buffer_sequence_adapter_base::native_buffer_type& buf, + const boost::asio::mutable_buffer& buffer) +{ + std::memset(&buf, 0, sizeof(native_buffer_type)); + Microsoft::WRL::ComPtr<IInspectable> insp + = Microsoft::WRL::Make<winrt_buffer_impl>(buffer); + buf = reinterpret_cast<Windows::Storage::Streams::IBuffer^>(insp.Get()); +} + +void buffer_sequence_adapter_base::init_native_buffer( + buffer_sequence_adapter_base::native_buffer_type& buf, + const boost::asio::const_buffer& buffer) +{ + std::memset(&buf, 0, sizeof(native_buffer_type)); + Microsoft::WRL::ComPtr<IInspectable> insp + = Microsoft::WRL::Make<winrt_buffer_impl>(buffer); + Platform::Object^ buf_obj = reinterpret_cast<Platform::Object^>(insp.Get()); + buf = reinterpret_cast<Windows::Storage::Streams::IBuffer^>(insp.Get()); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP
diff --git a/boost/boost/asio/detail/impl/descriptor_ops.ipp b/boost/boost/asio/detail/impl/descriptor_ops.ipp new file mode 100644 index 0000000..d700b22 --- /dev/null +++ b/boost/boost/asio/detail/impl/descriptor_ops.ipp
@@ -0,0 +1,453 @@ +// +// detail/impl/descriptor_ops.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_DESCRIPTOR_OPS_IPP +#define BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <cerrno> +#include <boost/asio/detail/descriptor_ops.hpp> +#include <boost/asio/error.hpp> + +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { +namespace descriptor_ops { + +int open(const char* path, int flags, boost::system::error_code& ec) +{ + errno = 0; + int result = error_wrapper(::open(path, flags), ec); + if (result >= 0) + ec = boost::system::error_code(); + return result; +} + +int close(int d, state_type& state, boost::system::error_code& ec) +{ + int result = 0; + if (d != -1) + { + errno = 0; + result = error_wrapper(::close(d), ec); + + if (result != 0 + && (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again)) + { + // According to UNIX Network Programming Vol. 1, it is possible for + // close() to fail with EWOULDBLOCK under certain circumstances. What + // isn't clear is the state of the descriptor after this error. The one + // current OS where this behaviour is seen, Windows, says that the socket + // remains open. Therefore we'll put the descriptor back into blocking + // mode and have another attempt at closing it. +#if defined(__SYMBIAN32__) + int flags = ::fcntl(d, F_GETFL, 0); + if (flags >= 0) + ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK); +#else // defined(__SYMBIAN32__) + ioctl_arg_type arg = 0; + ::ioctl(d, FIONBIO, &arg); +#endif // defined(__SYMBIAN32__) + state &= ~non_blocking; + + errno = 0; + result = error_wrapper(::close(d), ec); + } + } + + if (result == 0) + ec = boost::system::error_code(); + return result; +} + +bool set_user_non_blocking(int d, state_type& state, + bool value, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return false; + } + + errno = 0; +#if defined(__SYMBIAN32__) + int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec); + if (result >= 0) + { + errno = 0; + int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); + result = error_wrapper(::fcntl(d, F_SETFL, flag), ec); + } +#else // defined(__SYMBIAN32__) + ioctl_arg_type arg = (value ? 1 : 0); + int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec); +#endif // defined(__SYMBIAN32__) + + if (result >= 0) + { + ec = boost::system::error_code(); + if (value) + state |= user_set_non_blocking; + else + { + // Clearing the user-set non-blocking mode always overrides any + // internally-set non-blocking flag. Any subsequent asynchronous + // operations will need to re-enable non-blocking I/O. + state &= ~(user_set_non_blocking | internal_non_blocking); + } + return true; + } + + return false; +} + +bool set_internal_non_blocking(int d, state_type& state, + bool value, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return false; + } + + if (!value && (state & user_set_non_blocking)) + { + // It does not make sense to clear the internal non-blocking flag if the + // user still wants non-blocking behaviour. Return an error and let the + // caller figure out whether to update the user-set non-blocking flag. + ec = boost::asio::error::invalid_argument; + return false; + } + + errno = 0; +#if defined(__SYMBIAN32__) + int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec); + if (result >= 0) + { + errno = 0; + int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); + result = error_wrapper(::fcntl(d, F_SETFL, flag), ec); + } +#else // defined(__SYMBIAN32__) + ioctl_arg_type arg = (value ? 1 : 0); + int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec); +#endif // defined(__SYMBIAN32__) + + if (result >= 0) + { + ec = boost::system::error_code(); + if (value) + state |= internal_non_blocking; + else + state &= ~internal_non_blocking; + return true; + } + + return false; +} + +std::size_t sync_read(int d, state_type state, buf* bufs, + std::size_t count, bool all_empty, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // A request to read 0 bytes on a stream is a no-op. + if (all_empty) + { + ec = boost::system::error_code(); + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + errno = 0; + signed_size_type bytes = error_wrapper(::readv( + d, bufs, static_cast<int>(count)), ec); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Check for EOF. + if (bytes == 0) + { + ec = boost::asio::error::eof; + return 0; + } + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_read(d, 0, ec) < 0) + return 0; + } +} + +bool non_blocking_read(int d, buf* bufs, std::size_t count, + boost::system::error_code& ec, std::size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + errno = 0; + signed_size_type bytes = error_wrapper(::readv( + d, bufs, static_cast<int>(count)), ec); + + // Check for end of stream. + if (bytes == 0) + { + ec = boost::asio::error::eof; + return true; + } + + // Retry operation if interrupted by signal. + if (ec == boost::asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes > 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +std::size_t sync_write(int d, state_type state, const buf* bufs, + std::size_t count, bool all_empty, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // A request to write 0 bytes on a stream is a no-op. + if (all_empty) + { + ec = boost::system::error_code(); + return 0; + } + + // Write some data. + for (;;) + { + // Try to complete the operation without blocking. + errno = 0; + signed_size_type bytes = error_wrapper(::writev( + d, bufs, static_cast<int>(count)), ec); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_write(d, 0, ec) < 0) + return 0; + } +} + +bool non_blocking_write(int d, const buf* bufs, std::size_t count, + boost::system::error_code& ec, std::size_t& bytes_transferred) +{ + for (;;) + { + // Write some data. + errno = 0; + 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) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +int ioctl(int d, state_type& state, long cmd, + ioctl_arg_type* arg, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + errno = 0; + int result = error_wrapper(::ioctl(d, cmd, arg), ec); + + if (result >= 0) + { + ec = boost::system::error_code(); + + // When updating the non-blocking mode we always perform the ioctl syscall, + // even if the flags would otherwise indicate that the descriptor is + // already in the correct state. This ensures that the underlying + // descriptor is put into the state that has been requested by the user. If + // the ioctl syscall was successful then we need to update the flags to + // match. + if (cmd == static_cast<long>(FIONBIO)) + { + if (*arg) + { + state |= user_set_non_blocking; + } + else + { + // Clearing the non-blocking mode always overrides any internally-set + // non-blocking flag. Any subsequent asynchronous operations will need + // to re-enable non-blocking I/O. + state &= ~(user_set_non_blocking | internal_non_blocking); + } + } + } + + return result; +} + +int fcntl(int d, int cmd, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + errno = 0; + int result = error_wrapper(::fcntl(d, cmd), ec); + if (result != -1) + ec = boost::system::error_code(); + return result; +} + +int fcntl(int d, int cmd, long arg, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + errno = 0; + int result = error_wrapper(::fcntl(d, cmd, arg), ec); + if (result != -1) + ec = boost::system::error_code(); + return result; +} + +int poll_read(int d, state_type state, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + pollfd fds; + fds.fd = d; + fds.events = POLLIN; + fds.revents = 0; + int timeout = (state & user_set_non_blocking) ? 0 : -1; + errno = 0; + int result = error_wrapper(::poll(&fds, 1, timeout), ec); + if (result == 0) + ec = (state & user_set_non_blocking) + ? boost::asio::error::would_block : boost::system::error_code(); + else if (result > 0) + ec = boost::system::error_code(); + return result; +} + +int poll_write(int d, state_type state, boost::system::error_code& ec) +{ + if (d == -1) + { + ec = boost::asio::error::bad_descriptor; + return -1; + } + + pollfd fds; + fds.fd = d; + fds.events = POLLOUT; + fds.revents = 0; + int timeout = (state & user_set_non_blocking) ? 0 : -1; + errno = 0; + int result = error_wrapper(::poll(&fds, 1, timeout), ec); + if (result == 0) + ec = (state & user_set_non_blocking) + ? boost::asio::error::would_block : boost::system::error_code(); + else if (result > 0) + ec = boost::system::error_code(); + return result; +} + +} // namespace descriptor_ops +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) + +#endif // BOOST_ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
diff --git a/boost/boost/asio/detail/impl/dev_poll_reactor.hpp b/boost/boost/asio/detail/impl/dev_poll_reactor.hpp new file mode 100644 index 0000000..5ca6822 --- /dev/null +++ b/boost/boost/asio/detail/impl/dev_poll_reactor.hpp
@@ -0,0 +1,80 @@ +// +// detail/impl/dev_poll_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_DEV_POLL_REACTOR_HPP +#define BOOST_ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_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_DEV_POLL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Time_Traits> +void dev_poll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_add_timer_queue(queue); +} + +template <typename Time_Traits> +void dev_poll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_remove_timer_queue(queue); +} + +template <typename Time_Traits> +void dev_poll_reactor::schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + io_service_.post_immediate_completion(op, false); + return; + } + + bool earliest = queue.enqueue_timer(time, timer, op); + io_service_.work_started(); + if (earliest) + interrupter_.interrupt(); +} + +template <typename Time_Traits> +std::size_t dev_poll_reactor::cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + std::size_t n = queue.cancel_timer(timer, ops, max_cancelled); + lock.unlock(); + io_service_.post_deferred_completions(ops); + return n; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_DEV_POLL) + +#endif // BOOST_ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
diff --git a/boost/boost/asio/detail/impl/dev_poll_reactor.ipp b/boost/boost/asio/detail/impl/dev_poll_reactor.ipp new file mode 100644 index 0000000..aa276d3 --- /dev/null +++ b/boost/boost/asio/detail/impl/dev_poll_reactor.ipp
@@ -0,0 +1,432 @@ +// +// detail/impl/dev_poll_reactor.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_DEV_POLL_REACTOR_IPP +#define BOOST_ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_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_HAS_DEV_POLL) + +#include <boost/asio/detail/dev_poll_reactor.hpp> +#include <boost/asio/detail/assert.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +dev_poll_reactor::dev_poll_reactor(boost::asio::io_service& io_service) + : boost::asio::detail::service_base<dev_poll_reactor>(io_service), + io_service_(use_service<io_service_impl>(io_service)), + mutex_(), + dev_poll_fd_(do_dev_poll_create()), + interrupter_(), + shutdown_(false) +{ + // Add the interrupter's descriptor to /dev/poll. + ::pollfd ev = { 0, 0, 0 }; + ev.fd = interrupter_.read_descriptor(); + ev.events = POLLIN | POLLERR; + ev.revents = 0; + ::write(dev_poll_fd_, &ev, sizeof(ev)); +} + +dev_poll_reactor::~dev_poll_reactor() +{ + shutdown_service(); + ::close(dev_poll_fd_); +} + +void dev_poll_reactor::shutdown_service() +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + shutdown_ = true; + lock.unlock(); + + op_queue<operation> ops; + + for (int i = 0; i < max_ops; ++i) + op_queue_[i].get_all_operations(ops); + + timer_queues_.get_all_timers(ops); + + io_service_.abandon_operations(ops); +} + +void dev_poll_reactor::fork_service(boost::asio::io_service::fork_event fork_ev) +{ + if (fork_ev == boost::asio::io_service::fork_child) + { + detail::mutex::scoped_lock lock(mutex_); + + if (dev_poll_fd_ != -1) + ::close(dev_poll_fd_); + dev_poll_fd_ = -1; + dev_poll_fd_ = do_dev_poll_create(); + + interrupter_.recreate(); + + // Add the interrupter's descriptor to /dev/poll. + ::pollfd ev = { 0, 0, 0 }; + ev.fd = interrupter_.read_descriptor(); + ev.events = POLLIN | POLLERR; + ev.revents = 0; + ::write(dev_poll_fd_, &ev, sizeof(ev)); + + // Re-register all descriptors with /dev/poll. The changes will be written + // to the /dev/poll descriptor the next time the reactor is run. + for (int i = 0; i < max_ops; ++i) + { + reactor_op_queue<socket_type>::iterator iter = op_queue_[i].begin(); + reactor_op_queue<socket_type>::iterator end = op_queue_[i].end(); + for (; iter != end; ++iter) + { + ::pollfd& pending_ev = add_pending_event_change(iter->first); + pending_ev.events |= POLLERR | POLLHUP; + switch (i) + { + case read_op: pending_ev.events |= POLLIN; break; + case write_op: pending_ev.events |= POLLOUT; break; + case except_op: pending_ev.events |= POLLPRI; break; + default: break; + } + } + } + interrupter_.interrupt(); + } +} + +void dev_poll_reactor::init_task() +{ + io_service_.init_task(); +} + +int dev_poll_reactor::register_descriptor(socket_type, per_descriptor_data&) +{ + return 0; +} + +int dev_poll_reactor::register_internal_descriptor(int op_type, + socket_type descriptor, per_descriptor_data&, reactor_op* op) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + op_queue_[op_type].enqueue_operation(descriptor, op); + ::pollfd& ev = add_pending_event_change(descriptor); + ev.events = POLLERR | POLLHUP; + switch (op_type) + { + case read_op: ev.events |= POLLIN; break; + case write_op: ev.events |= POLLOUT; break; + case except_op: ev.events |= POLLPRI; break; + default: break; + } + interrupter_.interrupt(); + + return 0; +} + +void dev_poll_reactor::move_descriptor(socket_type, + dev_poll_reactor::per_descriptor_data&, + dev_poll_reactor::per_descriptor_data&) +{ +} + +void dev_poll_reactor::start_op(int op_type, socket_type descriptor, + dev_poll_reactor::per_descriptor_data&, reactor_op* op, + bool is_continuation, bool allow_speculative) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + post_immediate_completion(op, is_continuation); + return; + } + + if (allow_speculative) + { + if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor)) + { + if (!op_queue_[op_type].has_operation(descriptor)) + { + if (op->perform()) + { + lock.unlock(); + io_service_.post_immediate_completion(op, is_continuation); + return; + } + } + } + } + + bool first = op_queue_[op_type].enqueue_operation(descriptor, op); + io_service_.work_started(); + if (first) + { + ::pollfd& ev = add_pending_event_change(descriptor); + ev.events = POLLERR | POLLHUP; + if (op_type == read_op + || op_queue_[read_op].has_operation(descriptor)) + ev.events |= POLLIN; + if (op_type == write_op + || op_queue_[write_op].has_operation(descriptor)) + ev.events |= POLLOUT; + if (op_type == except_op + || op_queue_[except_op].has_operation(descriptor)) + ev.events |= POLLPRI; + interrupter_.interrupt(); + } +} + +void dev_poll_reactor::cancel_ops(socket_type descriptor, + dev_poll_reactor::per_descriptor_data&) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted); +} + +void dev_poll_reactor::deregister_descriptor(socket_type descriptor, + dev_poll_reactor::per_descriptor_data&, bool) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Remove the descriptor from /dev/poll. + ::pollfd& ev = add_pending_event_change(descriptor); + ev.events = POLLREMOVE; + interrupter_.interrupt(); + + // Cancel any outstanding operations associated with the descriptor. + cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted); +} + +void dev_poll_reactor::deregister_internal_descriptor( + socket_type descriptor, dev_poll_reactor::per_descriptor_data&) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Remove the descriptor from /dev/poll. Since this function is only called + // during a fork, we can apply the change immediately. + ::pollfd ev = { 0, 0, 0 }; + ev.fd = descriptor; + ev.events = POLLREMOVE; + ev.revents = 0; + ::write(dev_poll_fd_, &ev, sizeof(ev)); + + // Destroy all operations associated with the descriptor. + op_queue<operation> ops; + boost::system::error_code ec; + for (int i = 0; i < max_ops; ++i) + op_queue_[i].cancel_operations(descriptor, ops, ec); +} + +void dev_poll_reactor::run(bool block, op_queue<operation>& ops) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // We can return immediately if there's no work to do and the reactor is + // not supposed to block. + if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty() + && op_queue_[except_op].empty() && timer_queues_.all_empty()) + return; + + // Write the pending event registration changes to the /dev/poll descriptor. + std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size(); + if (events_size > 0) + { + errno = 0; + int result = ::write(dev_poll_fd_, + &pending_event_changes_[0], events_size); + if (result != static_cast<int>(events_size)) + { + boost::system::error_code ec = boost::system::error_code( + errno, boost::asio::error::get_system_category()); + for (std::size_t i = 0; i < pending_event_changes_.size(); ++i) + { + int descriptor = pending_event_changes_[i].fd; + for (int j = 0; j < max_ops; ++j) + op_queue_[j].cancel_operations(descriptor, ops, ec); + } + } + pending_event_changes_.clear(); + pending_event_change_index_.clear(); + } + + int timeout = block ? get_timeout() : 0; + lock.unlock(); + + // Block on the /dev/poll descriptor. + ::pollfd events[128] = { { 0, 0, 0 } }; + ::dvpoll dp = { 0, 0, 0 }; + dp.dp_fds = events; + dp.dp_nfds = 128; + dp.dp_timeout = timeout; + int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp); + + lock.lock(); + + // Dispatch the waiting events. + for (int i = 0; i < num_events; ++i) + { + int descriptor = events[i].fd; + if (descriptor == interrupter_.read_descriptor()) + { + interrupter_.reset(); + } + else + { + bool more_reads = false; + bool more_writes = false; + bool more_except = false; + + // Exception operations must be processed first to ensure that any + // out-of-band data is read before normal data. + if (events[i].events & (POLLPRI | POLLERR | POLLHUP)) + more_except = + op_queue_[except_op].perform_operations(descriptor, ops); + else + more_except = op_queue_[except_op].has_operation(descriptor); + + if (events[i].events & (POLLIN | POLLERR | POLLHUP)) + more_reads = op_queue_[read_op].perform_operations(descriptor, ops); + else + more_reads = op_queue_[read_op].has_operation(descriptor); + + if (events[i].events & (POLLOUT | POLLERR | POLLHUP)) + more_writes = op_queue_[write_op].perform_operations(descriptor, ops); + else + more_writes = op_queue_[write_op].has_operation(descriptor); + + if ((events[i].events & (POLLERR | POLLHUP)) != 0 + && !more_except && !more_reads && !more_writes) + { + // If we have an event and no operations associated with the + // descriptor then we need to delete the descriptor from /dev/poll. + // The poll operation can produce POLLHUP or POLLERR events when there + // is no operation pending, so if we do not remove the descriptor we + // can end up in a tight polling loop. + ::pollfd ev = { 0, 0, 0 }; + ev.fd = descriptor; + ev.events = POLLREMOVE; + ev.revents = 0; + ::write(dev_poll_fd_, &ev, sizeof(ev)); + } + else + { + ::pollfd ev = { 0, 0, 0 }; + ev.fd = descriptor; + ev.events = POLLERR | POLLHUP; + if (more_reads) + ev.events |= POLLIN; + if (more_writes) + ev.events |= POLLOUT; + if (more_except) + ev.events |= POLLPRI; + ev.revents = 0; + int result = ::write(dev_poll_fd_, &ev, sizeof(ev)); + if (result != sizeof(ev)) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + for (int j = 0; j < max_ops; ++j) + op_queue_[j].cancel_operations(descriptor, ops, ec); + } + } + } + } + timer_queues_.get_ready_timers(ops); +} + +void dev_poll_reactor::interrupt() +{ + interrupter_.interrupt(); +} + +int dev_poll_reactor::do_dev_poll_create() +{ + int fd = ::open("/dev/poll", O_RDWR); + if (fd == -1) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "/dev/poll"); + } + return fd; +} + +void dev_poll_reactor::do_add_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.insert(&queue); +} + +void dev_poll_reactor::do_remove_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.erase(&queue); +} + +int dev_poll_reactor::get_timeout() +{ + // By default we will wait no longer than 5 minutes. This will ensure that + // any changes to the system clock are detected after no longer than this. + return timer_queues_.wait_duration_msec(5 * 60 * 1000); +} + +void dev_poll_reactor::cancel_ops_unlocked(socket_type descriptor, + const boost::system::error_code& ec) +{ + bool need_interrupt = false; + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + need_interrupt = op_queue_[i].cancel_operations( + descriptor, ops, ec) || need_interrupt; + io_service_.post_deferred_completions(ops); + if (need_interrupt) + interrupter_.interrupt(); +} + +::pollfd& dev_poll_reactor::add_pending_event_change(int descriptor) +{ + hash_map<int, std::size_t>::iterator iter + = pending_event_change_index_.find(descriptor); + if (iter == pending_event_change_index_.end()) + { + std::size_t index = pending_event_changes_.size(); + pending_event_changes_.reserve(pending_event_changes_.size() + 1); + pending_event_change_index_.insert(std::make_pair(descriptor, index)); + pending_event_changes_.push_back(::pollfd()); + pending_event_changes_[index].fd = descriptor; + pending_event_changes_[index].revents = 0; + return pending_event_changes_[index]; + } + else + { + return pending_event_changes_[iter->second]; + } +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_DEV_POLL) + +#endif // BOOST_ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
diff --git a/boost/boost/asio/detail/impl/epoll_reactor.hpp b/boost/boost/asio/detail/impl/epoll_reactor.hpp new file mode 100644 index 0000000..dea5225 --- /dev/null +++ b/boost/boost/asio/detail/impl/epoll_reactor.hpp
@@ -0,0 +1,78 @@ +// +// detail/impl/epoll_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_EPOLL_REACTOR_HPP +#define BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#if defined(BOOST_ASIO_HAS_EPOLL) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Time_Traits> +void epoll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_add_timer_queue(queue); +} + +template <typename Time_Traits> +void epoll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_remove_timer_queue(queue); +} + +template <typename Time_Traits> +void epoll_reactor::schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op) +{ + mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + io_service_.post_immediate_completion(op, false); + return; + } + + bool earliest = queue.enqueue_timer(time, timer, op); + io_service_.work_started(); + if (earliest) + update_timeout(); +} + +template <typename Time_Traits> +std::size_t epoll_reactor::cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled) +{ + mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + std::size_t n = queue.cancel_timer(timer, ops, max_cancelled); + lock.unlock(); + io_service_.post_deferred_completions(ops); + return n; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_EPOLL) + +#endif // BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
diff --git a/boost/boost/asio/detail/impl/epoll_reactor.ipp b/boost/boost/asio/detail/impl/epoll_reactor.ipp new file mode 100644 index 0000000..accb0da --- /dev/null +++ b/boost/boost/asio/detail/impl/epoll_reactor.ipp
@@ -0,0 +1,664 @@ +// +// detail/impl/epoll_reactor.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_EPOLL_REACTOR_IPP +#define BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_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_HAS_EPOLL) + +#include <cstddef> +#include <sys/epoll.h> +#include <boost/asio/detail/epoll_reactor.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> + +#if defined(BOOST_ASIO_HAS_TIMERFD) +# include <sys/timerfd.h> +#endif // defined(BOOST_ASIO_HAS_TIMERFD) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +epoll_reactor::epoll_reactor(boost::asio::io_service& io_service) + : boost::asio::detail::service_base<epoll_reactor>(io_service), + io_service_(use_service<io_service_impl>(io_service)), + mutex_(), + interrupter_(), + epoll_fd_(do_epoll_create()), + timer_fd_(do_timerfd_create()), + shutdown_(false) +{ + // Add the interrupter's descriptor to epoll. + epoll_event ev = { 0, { 0 } }; + ev.events = EPOLLIN | EPOLLERR | EPOLLET; + ev.data.ptr = &interrupter_; + epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev); + interrupter_.interrupt(); + + // Add the timer descriptor to epoll. + if (timer_fd_ != -1) + { + ev.events = EPOLLIN | EPOLLERR; + ev.data.ptr = &timer_fd_; + epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev); + } +} + +epoll_reactor::~epoll_reactor() +{ + if (epoll_fd_ != -1) + close(epoll_fd_); + if (timer_fd_ != -1) + close(timer_fd_); +} + +void epoll_reactor::shutdown_service() +{ + mutex::scoped_lock lock(mutex_); + shutdown_ = true; + lock.unlock(); + + op_queue<operation> ops; + + while (descriptor_state* state = registered_descriptors_.first()) + { + for (int i = 0; i < max_ops; ++i) + ops.push(state->op_queue_[i]); + state->shutdown_ = true; + registered_descriptors_.free(state); + } + + timer_queues_.get_all_timers(ops); + + io_service_.abandon_operations(ops); +} + +void epoll_reactor::fork_service(boost::asio::io_service::fork_event fork_ev) +{ + if (fork_ev == boost::asio::io_service::fork_child) + { + if (epoll_fd_ != -1) + ::close(epoll_fd_); + epoll_fd_ = -1; + epoll_fd_ = do_epoll_create(); + + if (timer_fd_ != -1) + ::close(timer_fd_); + timer_fd_ = -1; + timer_fd_ = do_timerfd_create(); + + interrupter_.recreate(); + + // Add the interrupter's descriptor to epoll. + epoll_event ev = { 0, { 0 } }; + ev.events = EPOLLIN | EPOLLERR | EPOLLET; + ev.data.ptr = &interrupter_; + epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev); + interrupter_.interrupt(); + + // Add the timer descriptor to epoll. + if (timer_fd_ != -1) + { + ev.events = EPOLLIN | EPOLLERR; + ev.data.ptr = &timer_fd_; + epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev); + } + + update_timeout(); + + // Re-register all descriptors with epoll. + mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); + for (descriptor_state* state = registered_descriptors_.first(); + state != 0; state = state->next_) + { + ev.events = state->registered_events_; + ev.data.ptr = state; + int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, state->descriptor_, &ev); + if (result != 0) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "epoll re-registration"); + } + } + } +} + +void epoll_reactor::init_task() +{ + io_service_.init_task(); +} + +int epoll_reactor::register_descriptor(socket_type descriptor, + epoll_reactor::per_descriptor_data& descriptor_data) +{ + descriptor_data = allocate_descriptor_state(); + + { + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + descriptor_data->reactor_ = this; + descriptor_data->descriptor_ = descriptor; + descriptor_data->shutdown_ = false; + } + + epoll_event ev = { 0, { 0 } }; + 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) + return errno; + + return 0; +} + +int epoll_reactor::register_internal_descriptor( + int op_type, socket_type descriptor, + epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op) +{ + descriptor_data = allocate_descriptor_state(); + + { + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + descriptor_data->reactor_ = this; + descriptor_data->descriptor_ = descriptor; + descriptor_data->shutdown_ = false; + descriptor_data->op_queue_[op_type].push(op); + } + + epoll_event ev = { 0, { 0 } }; + 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) + return errno; + + return 0; +} + +void epoll_reactor::move_descriptor(socket_type, + epoll_reactor::per_descriptor_data& target_descriptor_data, + epoll_reactor::per_descriptor_data& source_descriptor_data) +{ + target_descriptor_data = source_descriptor_data; + source_descriptor_data = 0; +} + +void epoll_reactor::start_op(int op_type, socket_type descriptor, + epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op, + bool is_continuation, bool allow_speculative) +{ + if (!descriptor_data) + { + op->ec_ = boost::asio::error::bad_descriptor; + post_immediate_completion(op, is_continuation); + return; + } + + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + if (descriptor_data->shutdown_) + { + post_immediate_completion(op, is_continuation); + return; + } + + if (descriptor_data->op_queue_[op_type].empty()) + { + if (allow_speculative + && (op_type != read_op + || descriptor_data->op_queue_[except_op].empty())) + { + if (op->perform()) + { + descriptor_lock.unlock(); + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + if (op_type == write_op) + { + if ((descriptor_data->registered_events_ & EPOLLOUT) == 0) + { + 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, is_continuation); + return; + } + } + } + } + else + { + if (op_type == write_op) + { + descriptor_data->registered_events_ |= EPOLLOUT; + } + + epoll_event ev = { 0, { 0 } }; + ev.events = descriptor_data->registered_events_; + ev.data.ptr = descriptor_data; + epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); + } + } + + descriptor_data->op_queue_[op_type].push(op); + io_service_.work_started(); +} + +void epoll_reactor::cancel_ops(socket_type, + epoll_reactor::per_descriptor_data& descriptor_data) +{ + if (!descriptor_data) + return; + + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + { + while (reactor_op* op = descriptor_data->op_queue_[i].front()) + { + op->ec_ = boost::asio::error::operation_aborted; + descriptor_data->op_queue_[i].pop(); + ops.push(op); + } + } + + descriptor_lock.unlock(); + + io_service_.post_deferred_completions(ops); +} + +void epoll_reactor::deregister_descriptor(socket_type descriptor, + epoll_reactor::per_descriptor_data& descriptor_data, bool closing) +{ + if (!descriptor_data) + return; + + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + if (!descriptor_data->shutdown_) + { + if (closing) + { + // The descriptor will be automatically removed from the epoll set when + // it is closed. + } + else + { + epoll_event ev = { 0, { 0 } }; + epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); + } + + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + { + while (reactor_op* op = descriptor_data->op_queue_[i].front()) + { + op->ec_ = boost::asio::error::operation_aborted; + descriptor_data->op_queue_[i].pop(); + ops.push(op); + } + } + + descriptor_data->descriptor_ = -1; + descriptor_data->shutdown_ = true; + + descriptor_lock.unlock(); + + free_descriptor_state(descriptor_data); + descriptor_data = 0; + + io_service_.post_deferred_completions(ops); + } +} + +void epoll_reactor::deregister_internal_descriptor(socket_type descriptor, + epoll_reactor::per_descriptor_data& descriptor_data) +{ + if (!descriptor_data) + return; + + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + if (!descriptor_data->shutdown_) + { + epoll_event ev = { 0, { 0 } }; + epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); + + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + ops.push(descriptor_data->op_queue_[i]); + + descriptor_data->descriptor_ = -1; + descriptor_data->shutdown_ = true; + + descriptor_lock.unlock(); + + free_descriptor_state(descriptor_data); + descriptor_data = 0; + } +} + +void epoll_reactor::run(bool block, op_queue<operation>& ops) +{ + // This code relies on the fact that the task_io_service queues the reactor + // task behind all descriptor operations generated by this function. This + // means, that by the time we reach this point, any previously returned + // descriptor operations have already been dequeued. Therefore it is now safe + // for us to reuse and return them for the task_io_service to queue again. + + // Calculate a timeout only if timerfd is not used. + int timeout; + if (timer_fd_ != -1) + timeout = block ? -1 : 0; + else + { + mutex::scoped_lock lock(mutex_); + timeout = block ? get_timeout() : 0; + } + + // Block on the epoll descriptor. + epoll_event events[128]; + int num_events = epoll_wait(epoll_fd_, events, 128, timeout); + +#if defined(BOOST_ASIO_HAS_TIMERFD) + bool check_timers = (timer_fd_ == -1); +#else // defined(BOOST_ASIO_HAS_TIMERFD) + bool check_timers = true; +#endif // defined(BOOST_ASIO_HAS_TIMERFD) + + // Dispatch the waiting events. + for (int i = 0; i < num_events; ++i) + { + void* ptr = events[i].data.ptr; + if (ptr == &interrupter_) + { + // No need to reset the interrupter since we're leaving the descriptor + // in a ready-to-read state and relying on edge-triggered notifications + // to make it so that we only get woken up when the descriptor's epoll + // registration is updated. + +#if defined(BOOST_ASIO_HAS_TIMERFD) + if (timer_fd_ == -1) + check_timers = true; +#else // defined(BOOST_ASIO_HAS_TIMERFD) + check_timers = true; +#endif // defined(BOOST_ASIO_HAS_TIMERFD) + } +#if defined(BOOST_ASIO_HAS_TIMERFD) + else if (ptr == &timer_fd_) + { + check_timers = true; + } +#endif // defined(BOOST_ASIO_HAS_TIMERFD) + else + { + // The descriptor operation doesn't count as work in and of itself, so we + // don't call work_started() here. This still allows the io_service to + // stop if the only remaining operations are descriptor operations. + descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr); + descriptor_data->set_ready_events(events[i].events); + ops.push(descriptor_data); + } + } + + if (check_timers) + { + mutex::scoped_lock common_lock(mutex_); + timer_queues_.get_ready_timers(ops); + +#if defined(BOOST_ASIO_HAS_TIMERFD) + if (timer_fd_ != -1) + { + itimerspec new_timeout; + itimerspec old_timeout; + int flags = get_timeout(new_timeout); + timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout); + } +#endif // defined(BOOST_ASIO_HAS_TIMERFD) + } +} + +void epoll_reactor::interrupt() +{ + epoll_event ev = { 0, { 0 } }; + ev.events = EPOLLIN | EPOLLERR | EPOLLET; + ev.data.ptr = &interrupter_; + epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev); +} + +int epoll_reactor::do_epoll_create() +{ +#if defined(EPOLL_CLOEXEC) + int fd = epoll_create1(EPOLL_CLOEXEC); +#else // defined(EPOLL_CLOEXEC) + int fd = -1; + errno = EINVAL; +#endif // defined(EPOLL_CLOEXEC) + + if (fd == -1 && (errno == EINVAL || errno == ENOSYS)) + { + fd = epoll_create(epoll_size); + if (fd != -1) + ::fcntl(fd, F_SETFD, FD_CLOEXEC); + } + + if (fd == -1) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "epoll"); + } + + return fd; +} + +int epoll_reactor::do_timerfd_create() +{ +#if defined(BOOST_ASIO_HAS_TIMERFD) +# if defined(TFD_CLOEXEC) + int fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); +# else // defined(TFD_CLOEXEC) + int fd = -1; + errno = EINVAL; +# endif // defined(TFD_CLOEXEC) + + if (fd == -1 && errno == EINVAL) + { + fd = timerfd_create(CLOCK_MONOTONIC, 0); + if (fd != -1) + ::fcntl(fd, F_SETFD, FD_CLOEXEC); + } + + return fd; +#else // defined(BOOST_ASIO_HAS_TIMERFD) + return -1; +#endif // defined(BOOST_ASIO_HAS_TIMERFD) +} + +epoll_reactor::descriptor_state* epoll_reactor::allocate_descriptor_state() +{ + mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); + return registered_descriptors_.alloc(); +} + +void epoll_reactor::free_descriptor_state(epoll_reactor::descriptor_state* s) +{ + mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); + registered_descriptors_.free(s); +} + +void epoll_reactor::do_add_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.insert(&queue); +} + +void epoll_reactor::do_remove_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.erase(&queue); +} + +void epoll_reactor::update_timeout() +{ +#if defined(BOOST_ASIO_HAS_TIMERFD) + if (timer_fd_ != -1) + { + itimerspec new_timeout; + itimerspec old_timeout; + int flags = get_timeout(new_timeout); + timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout); + return; + } +#endif // defined(BOOST_ASIO_HAS_TIMERFD) + interrupt(); +} + +int epoll_reactor::get_timeout() +{ + // By default we will wait no longer than 5 minutes. This will ensure that + // any changes to the system clock are detected after no longer than this. + return timer_queues_.wait_duration_msec(5 * 60 * 1000); +} + +#if defined(BOOST_ASIO_HAS_TIMERFD) +int epoll_reactor::get_timeout(itimerspec& ts) +{ + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 0; + + long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000); + ts.it_value.tv_sec = usec / 1000000; + ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1; + + return usec ? 0 : TFD_TIMER_ABSTIME; +} +#endif // defined(BOOST_ASIO_HAS_TIMERFD) + +struct epoll_reactor::perform_io_cleanup_on_block_exit +{ + explicit perform_io_cleanup_on_block_exit(epoll_reactor* r) + : reactor_(r), first_op_(0) + { + } + + ~perform_io_cleanup_on_block_exit() + { + if (first_op_) + { + // Post the remaining completed operations for invocation. + if (!ops_.empty()) + reactor_->io_service_.post_deferred_completions(ops_); + + // A user-initiated operation has completed, but there's no need to + // explicitly call work_finished() here. Instead, we'll take advantage of + // the fact that the task_io_service will call work_finished() once we + // return. + } + else + { + // No user-initiated operations have completed, so we need to compensate + // for the work_finished() call that the task_io_service will make once + // this operation returns. + reactor_->io_service_.work_started(); + } + } + + epoll_reactor* reactor_; + op_queue<operation> ops_; + operation* first_op_; +}; + +epoll_reactor::descriptor_state::descriptor_state() + : operation(&epoll_reactor::descriptor_state::do_complete) +{ +} + +operation* epoll_reactor::descriptor_state::perform_io(uint32_t events) +{ + mutex_.lock(); + perform_io_cleanup_on_block_exit io_cleanup(reactor_); + mutex::scoped_lock descriptor_lock(mutex_, mutex::scoped_lock::adopt_lock); + + // Exception operations must be processed first to ensure that any + // out-of-band data is read before normal data. + static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI }; + for (int j = max_ops - 1; j >= 0; --j) + { + if (events & (flag[j] | EPOLLERR | EPOLLHUP)) + { + while (reactor_op* op = op_queue_[j].front()) + { + if (op->perform()) + { + op_queue_[j].pop(); + io_cleanup.ops_.push(op); + } + else + break; + } + } + } + + // The first operation will be returned for completion now. The others will + // be posted for later by the io_cleanup object's destructor. + io_cleanup.first_op_ = io_cleanup.ops_.front(); + io_cleanup.ops_.pop(); + return io_cleanup.first_op_; +} + +void epoll_reactor::descriptor_state::do_complete( + io_service_impl* owner, operation* base, + const boost::system::error_code& ec, std::size_t bytes_transferred) +{ + if (owner) + { + descriptor_state* descriptor_data = static_cast<descriptor_state*>(base); + uint32_t events = static_cast<uint32_t>(bytes_transferred); + if (operation* op = descriptor_data->perform_io(events)) + { + op->complete(*owner, ec, 0); + } + } +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_EPOLL) + +#endif // BOOST_ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
diff --git a/boost/boost/asio/detail/impl/eventfd_select_interrupter.ipp b/boost/boost/asio/detail/impl/eventfd_select_interrupter.ipp new file mode 100644 index 0000000..cde54b9 --- /dev/null +++ b/boost/boost/asio/detail/impl/eventfd_select_interrupter.ipp
@@ -0,0 +1,167 @@ +// +// detail/impl/eventfd_select_interrupter.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail 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_EVENTFD_SELECT_INTERRUPTER_IPP +#define BOOST_ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_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_HAS_EVENTFD) + +#include <sys/stat.h> +#include <sys/types.h> +#include <fcntl.h> +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +# include <asm/unistd.h> +#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +# include <sys/eventfd.h> +#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +#include <boost/asio/detail/cstdint.hpp> +#include <boost/asio/detail/eventfd_select_interrupter.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +eventfd_select_interrupter::eventfd_select_interrupter() +{ + open_descriptors(); +} + +void eventfd_select_interrupter::open_descriptors() +{ +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 + write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0); + if (read_descriptor_ != -1) + { + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + } +#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 +# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + write_descriptor_ = read_descriptor_ = + ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); +# else // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + errno = EINVAL; + write_descriptor_ = read_descriptor_ = -1; +# endif // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) + if (read_descriptor_ == -1 && errno == EINVAL) + { + write_descriptor_ = read_descriptor_ = ::eventfd(0, 0); + if (read_descriptor_ != -1) + { + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + } + } +#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 + + if (read_descriptor_ == -1) + { + int pipe_fds[2]; + if (pipe(pipe_fds) == 0) + { + read_descriptor_ = pipe_fds[0]; + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + write_descriptor_ = pipe_fds[1]; + ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); + ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC); + } + else + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "eventfd_select_interrupter"); + } + } +} + +eventfd_select_interrupter::~eventfd_select_interrupter() +{ + close_descriptors(); +} + +void eventfd_select_interrupter::close_descriptors() +{ + if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_) + ::close(write_descriptor_); + if (read_descriptor_ != -1) + ::close(read_descriptor_); +} + +void eventfd_select_interrupter::recreate() +{ + close_descriptors(); + + write_descriptor_ = -1; + read_descriptor_ = -1; + + open_descriptors(); +} + +void eventfd_select_interrupter::interrupt() +{ + uint64_t counter(1UL); + int result = ::write(write_descriptor_, &counter, sizeof(uint64_t)); + (void)result; +} + +bool eventfd_select_interrupter::reset() +{ + if (write_descriptor_ == read_descriptor_) + { + for (;;) + { + // Only perform one read. The kernel maintains an atomic counter. + uint64_t counter(0); + errno = 0; + int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t)); + if (bytes_read < 0 && errno == EINTR) + continue; + bool was_interrupted = (bytes_read > 0); + return was_interrupted; + } + } + else + { + for (;;) + { + // Clear all data from the pipe. + char data[1024]; + int bytes_read = ::read(read_descriptor_, data, sizeof(data)); + if (bytes_read < 0 && errno == EINTR) + continue; + bool was_interrupted = (bytes_read > 0); + while (bytes_read == sizeof(data)) + bytes_read = ::read(read_descriptor_, data, sizeof(data)); + return was_interrupted; + } + } +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_EVENTFD) + +#endif // BOOST_ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
diff --git a/boost/boost/asio/detail/impl/handler_tracking.ipp b/boost/boost/asio/detail/impl/handler_tracking.ipp new file mode 100644 index 0000000..4a07911 --- /dev/null +++ b/boost/boost/asio/detail/impl/handler_tracking.ipp
@@ -0,0 +1,307 @@ +// +// detail/impl/handler_tracking.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_HANDLER_TRACKING_IPP +#define BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_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_ENABLE_HANDLER_TRACKING) + +#include <cstdarg> +#include <cstdio> +#include <boost/asio/detail/handler_tracking.hpp> + +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) +# include <boost/asio/time_traits.hpp> +#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) +# if defined(BOOST_ASIO_HAS_STD_CHRONO) +# include <chrono> +# elif defined(BOOST_ASIO_HAS_BOOST_CHRONO) +# include <boost/chrono/system_clocks.hpp> +# endif +# include <boost/asio/detail/chrono_time_traits.hpp> +# include <boost/asio/wait_traits.hpp> +#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) + +#if !defined(BOOST_ASIO_WINDOWS) +# include <unistd.h> +#endif // !defined(BOOST_ASIO_WINDOWS) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +struct handler_tracking_timestamp +{ + uint64_t seconds; + uint64_t microseconds; + + handler_tracking_timestamp() + { +#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) + boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1)); + boost::posix_time::time_duration now = + boost::posix_time::microsec_clock::universal_time() - epoch; +#elif defined(BOOST_ASIO_HAS_STD_CHRONO) + typedef chrono_time_traits<std::chrono::system_clock, + boost::asio::wait_traits<std::chrono::system_clock> > traits_helper; + traits_helper::posix_time_duration now( + std::chrono::system_clock::now().time_since_epoch()); +#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO) + typedef chrono_time_traits<boost::chrono::system_clock, + boost::asio::wait_traits<boost::chrono::system_clock> > traits_helper; + traits_helper::posix_time_duration now( + boost::chrono::system_clock::now().time_since_epoch()); +#endif + seconds = static_cast<uint64_t>(now.total_seconds()); + microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000); + } +}; + +struct handler_tracking::tracking_state +{ + static_mutex mutex_; + uint64_t next_id_; + tss_ptr<completion>* current_completion_; +}; + +handler_tracking::tracking_state* handler_tracking::get_state() +{ + static tracking_state state = { BOOST_ASIO_STATIC_MUTEX_INIT, 1, 0 }; + return &state; +} + +void handler_tracking::init() +{ + static tracking_state* state = get_state(); + + state->mutex_.init(); + + static_mutex::scoped_lock lock(state->mutex_); + if (state->current_completion_ == 0) + state->current_completion_ = new tss_ptr<completion>; +} + +void handler_tracking::creation(handler_tracking::tracked_handler* h, + const char* object_type, void* object, const char* op_name) +{ + static tracking_state* state = get_state(); + + static_mutex::scoped_lock lock(state->mutex_); + h->id_ = state->next_id_++; + lock.unlock(); + + handler_tracking_timestamp timestamp; + + uint64_t current_id = 0; + if (completion* current_completion = *state->current_completion_) + current_id = current_completion->id_; + + write_line( +#if defined(BOOST_ASIO_WINDOWS) + "@asio|%I64u.%06I64u|%I64u*%I64u|%.20s@%p.%.50s\n", +#else // defined(BOOST_ASIO_WINDOWS) + "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n", +#endif // defined(BOOST_ASIO_WINDOWS) + timestamp.seconds, timestamp.microseconds, + current_id, h->id_, object_type, object, op_name); +} + +handler_tracking::completion::completion(handler_tracking::tracked_handler* h) + : id_(h->id_), + invoked_(false), + next_(*get_state()->current_completion_) +{ + *get_state()->current_completion_ = this; +} + +handler_tracking::completion::~completion() +{ + if (id_) + { + handler_tracking_timestamp timestamp; + + write_line( +#if defined(BOOST_ASIO_WINDOWS) + "@asio|%I64u.%06I64u|%c%I64u|\n", +#else // defined(BOOST_ASIO_WINDOWS) + "@asio|%llu.%06llu|%c%llu|\n", +#endif // defined(BOOST_ASIO_WINDOWS) + timestamp.seconds, timestamp.microseconds, + invoked_ ? '!' : '~', id_); + } + + *get_state()->current_completion_ = next_; +} + +void handler_tracking::completion::invocation_begin() +{ + handler_tracking_timestamp timestamp; + + write_line( +#if defined(BOOST_ASIO_WINDOWS) + "@asio|%I64u.%06I64u|>%I64u|\n", +#else // defined(BOOST_ASIO_WINDOWS) + "@asio|%llu.%06llu|>%llu|\n", +#endif // defined(BOOST_ASIO_WINDOWS) + timestamp.seconds, timestamp.microseconds, id_); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_begin( + const boost::system::error_code& ec) +{ + handler_tracking_timestamp timestamp; + + write_line( +#if defined(BOOST_ASIO_WINDOWS) + "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d\n", +#else // defined(BOOST_ASIO_WINDOWS) + "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n", +#endif // defined(BOOST_ASIO_WINDOWS) + timestamp.seconds, timestamp.microseconds, + id_, ec.category().name(), ec.value()); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_begin( + const boost::system::error_code& ec, std::size_t bytes_transferred) +{ + handler_tracking_timestamp timestamp; + + write_line( +#if defined(BOOST_ASIO_WINDOWS) + "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,bytes_transferred=%I64u\n", +#else // defined(BOOST_ASIO_WINDOWS) + "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n", +#endif // defined(BOOST_ASIO_WINDOWS) + timestamp.seconds, timestamp.microseconds, + id_, ec.category().name(), ec.value(), + static_cast<uint64_t>(bytes_transferred)); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_begin( + const boost::system::error_code& ec, int signal_number) +{ + handler_tracking_timestamp timestamp; + + write_line( +#if defined(BOOST_ASIO_WINDOWS) + "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,signal_number=%d\n", +#else // defined(BOOST_ASIO_WINDOWS) + "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n", +#endif // defined(BOOST_ASIO_WINDOWS) + timestamp.seconds, timestamp.microseconds, + id_, ec.category().name(), ec.value(), signal_number); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_begin( + const boost::system::error_code& ec, const char* arg) +{ + handler_tracking_timestamp timestamp; + + write_line( +#if defined(BOOST_ASIO_WINDOWS) + "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,%.50s\n", +#else // defined(BOOST_ASIO_WINDOWS) + "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n", +#endif // defined(BOOST_ASIO_WINDOWS) + timestamp.seconds, timestamp.microseconds, + id_, ec.category().name(), ec.value(), arg); + + invoked_ = true; +} + +void handler_tracking::completion::invocation_end() +{ + if (id_) + { + handler_tracking_timestamp timestamp; + + write_line( +#if defined(BOOST_ASIO_WINDOWS) + "@asio|%I64u.%06I64u|<%I64u|\n", +#else // defined(BOOST_ASIO_WINDOWS) + "@asio|%llu.%06llu|<%llu|\n", +#endif // defined(BOOST_ASIO_WINDOWS) + timestamp.seconds, timestamp.microseconds, id_); + + id_ = 0; + } +} + +void handler_tracking::operation(const char* object_type, + void* object, const char* op_name) +{ + static tracking_state* state = get_state(); + + handler_tracking_timestamp timestamp; + + unsigned long long current_id = 0; + if (completion* current_completion = *state->current_completion_) + current_id = current_completion->id_; + + write_line( +#if defined(BOOST_ASIO_WINDOWS) + "@asio|%I64u.%06I64u|%I64u|%.20s@%p.%.50s\n", +#else // defined(BOOST_ASIO_WINDOWS) + "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n", +#endif // defined(BOOST_ASIO_WINDOWS) + timestamp.seconds, timestamp.microseconds, + current_id, object_type, object, op_name); +} + +void handler_tracking::write_line(const char* format, ...) +{ + using namespace std; // For sprintf (or equivalent). + + va_list args; + va_start(args, format); + + char line[256] = ""; +#if defined(BOOST_ASIO_HAS_SECURE_RTL) + int length = vsprintf_s(line, sizeof(line), format, args); +#else // defined(BOOST_ASIO_HAS_SECURE_RTL) + int length = vsprintf(line, format, args); +#endif // defined(BOOST_ASIO_HAS_SECURE_RTL) + + va_end(args); + +#if defined(BOOST_ASIO_WINDOWS) + HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE); + DWORD bytes_written = 0; + ::WriteFile(stderr_handle, line, length, &bytes_written, 0); +#else // defined(BOOST_ASIO_WINDOWS) + ::write(STDERR_FILENO, line, length); +#endif // defined(BOOST_ASIO_WINDOWS) +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING) + +#endif // BOOST_ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
diff --git a/boost/boost/asio/detail/impl/kqueue_reactor.hpp b/boost/boost/asio/detail/impl/kqueue_reactor.hpp new file mode 100644 index 0000000..807c121 --- /dev/null +++ b/boost/boost/asio/detail/impl/kqueue_reactor.hpp
@@ -0,0 +1,82 @@ +// +// detail/impl/kqueue_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP +#define BOOST_ASIO_DETAIL_IMPL_KQUEUE_REACTOR_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_KQUEUE) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Time_Traits> +void kqueue_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_add_timer_queue(queue); +} + +// Remove a timer queue from the reactor. +template <typename Time_Traits> +void kqueue_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_remove_timer_queue(queue); +} + +template <typename Time_Traits> +void kqueue_reactor::schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + io_service_.post_immediate_completion(op, false); + return; + } + + bool earliest = queue.enqueue_timer(time, timer, op); + io_service_.work_started(); + if (earliest) + interrupt(); +} + +template <typename Time_Traits> +std::size_t kqueue_reactor::cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + std::size_t n = queue.cancel_timer(timer, ops, max_cancelled); + lock.unlock(); + io_service_.post_deferred_completions(ops); + return n; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_KQUEUE) + +#endif // BOOST_ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
diff --git a/boost/boost/asio/detail/impl/kqueue_reactor.ipp b/boost/boost/asio/detail/impl/kqueue_reactor.ipp new file mode 100644 index 0000000..70aeb38 --- /dev/null +++ b/boost/boost/asio/detail/impl/kqueue_reactor.ipp
@@ -0,0 +1,498 @@ +// +// detail/impl/kqueue_reactor.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP +#define BOOST_ASIO_DETAIL_IMPL_KQUEUE_REACTOR_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_HAS_KQUEUE) + +#include <boost/asio/detail/kqueue_reactor.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> + +#include <boost/asio/detail/push_options.hpp> + +#if defined(__NetBSD__) +# define BOOST_ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \ + EV_SET(ev, ident, filt, flags, fflags, data, \ + reinterpret_cast<intptr_t>(static_cast<void*>(udata))) +#else +# define BOOST_ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \ + EV_SET(ev, ident, filt, flags, fflags, data, udata) +#endif + +namespace boost { +namespace asio { +namespace detail { + +kqueue_reactor::kqueue_reactor(boost::asio::io_service& io_service) + : boost::asio::detail::service_base<kqueue_reactor>(io_service), + io_service_(use_service<io_service_impl>(io_service)), + mutex_(), + kqueue_fd_(do_kqueue_create()), + interrupter_(), + shutdown_(false) +{ + struct kevent events[1]; + BOOST_ASIO_KQUEUE_EV_SET(&events[0], interrupter_.read_descriptor(), + EVFILT_READ, EV_ADD, 0, 0, &interrupter_); + if (::kevent(kqueue_fd_, events, 1, 0, 0, 0) == -1) + { + boost::system::error_code error(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(error); + } +} + +kqueue_reactor::~kqueue_reactor() +{ + close(kqueue_fd_); +} + +void kqueue_reactor::shutdown_service() +{ + mutex::scoped_lock lock(mutex_); + shutdown_ = true; + lock.unlock(); + + op_queue<operation> ops; + + while (descriptor_state* state = registered_descriptors_.first()) + { + for (int i = 0; i < max_ops; ++i) + ops.push(state->op_queue_[i]); + state->shutdown_ = true; + registered_descriptors_.free(state); + } + + timer_queues_.get_all_timers(ops); + + io_service_.abandon_operations(ops); +} + +void kqueue_reactor::fork_service(boost::asio::io_service::fork_event fork_ev) +{ + if (fork_ev == boost::asio::io_service::fork_child) + { + // The kqueue descriptor is automatically closed in the child. + kqueue_fd_ = -1; + kqueue_fd_ = do_kqueue_create(); + + interrupter_.recreate(); + + struct kevent events[2]; + BOOST_ASIO_KQUEUE_EV_SET(&events[0], interrupter_.read_descriptor(), + EVFILT_READ, EV_ADD, 0, 0, &interrupter_); + if (::kevent(kqueue_fd_, events, 1, 0, 0, 0) == -1) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "kqueue interrupter registration"); + } + + // Re-register all descriptors with kqueue. + mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); + for (descriptor_state* state = registered_descriptors_.first(); + state != 0; state = state->next_) + { + if (state->num_kevents_ > 0) + { + BOOST_ASIO_KQUEUE_EV_SET(&events[0], state->descriptor_, + EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, state); + BOOST_ASIO_KQUEUE_EV_SET(&events[1], state->descriptor_, + EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, state); + if (::kevent(kqueue_fd_, events, state->num_kevents_, 0, 0, 0) == -1) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "kqueue re-registration"); + } + } + } + } +} + +void kqueue_reactor::init_task() +{ + io_service_.init_task(); +} + +int kqueue_reactor::register_descriptor(socket_type descriptor, + kqueue_reactor::per_descriptor_data& descriptor_data) +{ + descriptor_data = allocate_descriptor_state(); + + mutex::scoped_lock lock(descriptor_data->mutex_); + + descriptor_data->descriptor_ = descriptor; + descriptor_data->num_kevents_ = 0; + descriptor_data->shutdown_ = false; + + return 0; +} + +int kqueue_reactor::register_internal_descriptor( + int op_type, socket_type descriptor, + kqueue_reactor::per_descriptor_data& descriptor_data, reactor_op* op) +{ + descriptor_data = allocate_descriptor_state(); + + mutex::scoped_lock lock(descriptor_data->mutex_); + + descriptor_data->descriptor_ = descriptor; + descriptor_data->num_kevents_ = 1; + descriptor_data->shutdown_ = false; + descriptor_data->op_queue_[op_type].push(op); + + struct kevent events[1]; + BOOST_ASIO_KQUEUE_EV_SET(&events[0], descriptor, EVFILT_READ, + EV_ADD | EV_CLEAR, 0, 0, descriptor_data); + if (::kevent(kqueue_fd_, events, 1, 0, 0, 0) == -1) + return errno; + + return 0; +} + +void kqueue_reactor::move_descriptor(socket_type, + kqueue_reactor::per_descriptor_data& target_descriptor_data, + kqueue_reactor::per_descriptor_data& source_descriptor_data) +{ + target_descriptor_data = source_descriptor_data; + source_descriptor_data = 0; +} + +void kqueue_reactor::start_op(int op_type, socket_type descriptor, + kqueue_reactor::per_descriptor_data& descriptor_data, reactor_op* op, + bool is_continuation, bool allow_speculative) +{ + if (!descriptor_data) + { + op->ec_ = boost::asio::error::bad_descriptor; + post_immediate_completion(op, is_continuation); + return; + } + + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + if (descriptor_data->shutdown_) + { + post_immediate_completion(op, is_continuation); + return; + } + + if (descriptor_data->op_queue_[op_type].empty()) + { + static const int num_kevents[max_ops] = { 1, 2, 1 }; + + if (allow_speculative + && (op_type != read_op + || descriptor_data->op_queue_[except_op].empty())) + { + if (op->perform()) + { + descriptor_lock.unlock(); + io_service_.post_immediate_completion(op, is_continuation); + return; + } + + if (descriptor_data->num_kevents_ < num_kevents[op_type]) + { + struct kevent events[2]; + BOOST_ASIO_KQUEUE_EV_SET(&events[0], descriptor, EVFILT_READ, + EV_ADD | EV_CLEAR, 0, 0, descriptor_data); + BOOST_ASIO_KQUEUE_EV_SET(&events[1], descriptor, EVFILT_WRITE, + EV_ADD | EV_CLEAR, 0, 0, descriptor_data); + if (::kevent(kqueue_fd_, events, num_kevents[op_type], 0, 0, 0) != -1) + { + descriptor_data->num_kevents_ = num_kevents[op_type]; + } + else + { + op->ec_ = boost::system::error_code(errno, + boost::asio::error::get_system_category()); + io_service_.post_immediate_completion(op, is_continuation); + return; + } + } + } + else + { + if (descriptor_data->num_kevents_ < num_kevents[op_type]) + descriptor_data->num_kevents_ = num_kevents[op_type]; + + struct kevent events[2]; + BOOST_ASIO_KQUEUE_EV_SET(&events[0], descriptor, EVFILT_READ, + EV_ADD | EV_CLEAR, 0, 0, descriptor_data); + BOOST_ASIO_KQUEUE_EV_SET(&events[1], descriptor, EVFILT_WRITE, + EV_ADD | EV_CLEAR, 0, 0, descriptor_data); + ::kevent(kqueue_fd_, events, descriptor_data->num_kevents_, 0, 0, 0); + } + } + + descriptor_data->op_queue_[op_type].push(op); + io_service_.work_started(); +} + +void kqueue_reactor::cancel_ops(socket_type, + kqueue_reactor::per_descriptor_data& descriptor_data) +{ + if (!descriptor_data) + return; + + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + { + while (reactor_op* op = descriptor_data->op_queue_[i].front()) + { + op->ec_ = boost::asio::error::operation_aborted; + descriptor_data->op_queue_[i].pop(); + ops.push(op); + } + } + + descriptor_lock.unlock(); + + io_service_.post_deferred_completions(ops); +} + +void kqueue_reactor::deregister_descriptor(socket_type descriptor, + kqueue_reactor::per_descriptor_data& descriptor_data, bool closing) +{ + if (!descriptor_data) + return; + + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + if (!descriptor_data->shutdown_) + { + if (closing) + { + // The descriptor will be automatically removed from the kqueue when it + // is closed. + } + else + { + struct kevent events[2]; + BOOST_ASIO_KQUEUE_EV_SET(&events[0], descriptor, + EVFILT_READ, EV_DELETE, 0, 0, 0); + BOOST_ASIO_KQUEUE_EV_SET(&events[1], descriptor, + EVFILT_WRITE, EV_DELETE, 0, 0, 0); + ::kevent(kqueue_fd_, events, descriptor_data->num_kevents_, 0, 0, 0); + } + + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + { + while (reactor_op* op = descriptor_data->op_queue_[i].front()) + { + op->ec_ = boost::asio::error::operation_aborted; + descriptor_data->op_queue_[i].pop(); + ops.push(op); + } + } + + descriptor_data->descriptor_ = -1; + descriptor_data->shutdown_ = true; + + descriptor_lock.unlock(); + + free_descriptor_state(descriptor_data); + descriptor_data = 0; + + io_service_.post_deferred_completions(ops); + } +} + +void kqueue_reactor::deregister_internal_descriptor(socket_type descriptor, + kqueue_reactor::per_descriptor_data& descriptor_data) +{ + if (!descriptor_data) + return; + + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + if (!descriptor_data->shutdown_) + { + struct kevent events[2]; + BOOST_ASIO_KQUEUE_EV_SET(&events[0], descriptor, + EVFILT_READ, EV_DELETE, 0, 0, 0); + BOOST_ASIO_KQUEUE_EV_SET(&events[1], descriptor, + EVFILT_WRITE, EV_DELETE, 0, 0, 0); + ::kevent(kqueue_fd_, events, descriptor_data->num_kevents_, 0, 0, 0); + + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + ops.push(descriptor_data->op_queue_[i]); + + descriptor_data->descriptor_ = -1; + descriptor_data->shutdown_ = true; + + descriptor_lock.unlock(); + + free_descriptor_state(descriptor_data); + descriptor_data = 0; + } +} + +void kqueue_reactor::run(bool block, op_queue<operation>& ops) +{ + mutex::scoped_lock lock(mutex_); + + // Determine how long to block while waiting for events. + timespec timeout_buf = { 0, 0 }; + timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf; + + lock.unlock(); + + // Block on the kqueue descriptor. + struct kevent events[128]; + int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout); + + // Dispatch the waiting events. + for (int i = 0; i < num_events; ++i) + { + void* ptr = reinterpret_cast<void*>(events[i].udata); + if (ptr == &interrupter_) + { + interrupter_.reset(); + } + else + { + descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr); + mutex::scoped_lock descriptor_lock(descriptor_data->mutex_); + + if (events[i].filter == EVFILT_WRITE + && descriptor_data->num_kevents_ == 2 + && descriptor_data->op_queue_[write_op].empty()) + { + // Some descriptor types, like serial ports, don't seem to support + // EV_CLEAR with EVFILT_WRITE. Since we have no pending write + // operations we'll remove the EVFILT_WRITE registration here so that + // we don't end up in a tight spin. + struct kevent delete_events[1]; + BOOST_ASIO_KQUEUE_EV_SET(&delete_events[0], + descriptor_data->descriptor_, EVFILT_WRITE, EV_DELETE, 0, 0, 0); + ::kevent(kqueue_fd_, delete_events, 1, 0, 0, 0); + descriptor_data->num_kevents_ = 1; + } + + // Exception operations must be processed first to ensure that any + // out-of-band data is read before normal data. +#if defined(__NetBSD__) + static const unsigned int filter[max_ops] = +#else + static const int filter[max_ops] = +#endif + { EVFILT_READ, EVFILT_WRITE, EVFILT_READ }; + for (int j = max_ops - 1; j >= 0; --j) + { + if (events[i].filter == filter[j]) + { + if (j != except_op || events[i].flags & EV_OOBAND) + { + while (reactor_op* op = descriptor_data->op_queue_[j].front()) + { + if (events[i].flags & EV_ERROR) + { + 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); + } + if (op->perform()) + { + descriptor_data->op_queue_[j].pop(); + ops.push(op); + } + else + break; + } + } + } + } + } + } + + lock.lock(); + timer_queues_.get_ready_timers(ops); +} + +void kqueue_reactor::interrupt() +{ + interrupter_.interrupt(); +} + +int kqueue_reactor::do_kqueue_create() +{ + int fd = ::kqueue(); + if (fd == -1) + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "kqueue"); + } + return fd; +} + +kqueue_reactor::descriptor_state* kqueue_reactor::allocate_descriptor_state() +{ + mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); + return registered_descriptors_.alloc(); +} + +void kqueue_reactor::free_descriptor_state(kqueue_reactor::descriptor_state* s) +{ + mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_); + registered_descriptors_.free(s); +} + +void kqueue_reactor::do_add_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.insert(&queue); +} + +void kqueue_reactor::do_remove_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.erase(&queue); +} + +timespec* kqueue_reactor::get_timeout(timespec& ts) +{ + // By default we will wait no longer than 5 minutes. This will ensure that + // any changes to the system clock are detected after no longer than this. + long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000); + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + return &ts; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#undef BOOST_ASIO_KQUEUE_EV_SET + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_KQUEUE) + +#endif // BOOST_ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
diff --git a/boost/boost/asio/detail/impl/pipe_select_interrupter.ipp b/boost/boost/asio/detail/impl/pipe_select_interrupter.ipp new file mode 100644 index 0000000..c48e61d --- /dev/null +++ b/boost/boost/asio/detail/impl/pipe_select_interrupter.ipp
@@ -0,0 +1,126 @@ +// +// detail/impl/pipe_select_interrupter.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_PIPE_SELECT_INTERRUPTER_IPP +#define BOOST_ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_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_WINDOWS_RUNTIME) +#if !defined(BOOST_ASIO_WINDOWS) +#if !defined(__CYGWIN__) +#if !defined(__SYMBIAN32__) +#if !defined(BOOST_ASIO_HAS_EVENTFD) + +#include <fcntl.h> +#include <sys/stat.h> +#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> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +pipe_select_interrupter::pipe_select_interrupter() +{ + open_descriptors(); +} + +void pipe_select_interrupter::open_descriptors() +{ + int pipe_fds[2]; + if (pipe(pipe_fds) == 0) + { + read_descriptor_ = pipe_fds[0]; + ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); + write_descriptor_ = pipe_fds[1]; + ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); + +#if defined(FD_CLOEXEC) + ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); + ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC); +#endif // defined(FD_CLOEXEC) + } + else + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "pipe_select_interrupter"); + } +} + +pipe_select_interrupter::~pipe_select_interrupter() +{ + close_descriptors(); +} + +void pipe_select_interrupter::close_descriptors() +{ + if (read_descriptor_ != -1) + ::close(read_descriptor_); + if (write_descriptor_ != -1) + ::close(write_descriptor_); +} + +void pipe_select_interrupter::recreate() +{ + close_descriptors(); + + write_descriptor_ = -1; + read_descriptor_ = -1; + + open_descriptors(); +} + +void pipe_select_interrupter::interrupt() +{ + char byte = 0; + signed_size_type result = ::write(write_descriptor_, &byte, 1); + (void)result; +} + +bool pipe_select_interrupter::reset() +{ + for (;;) + { + char data[1024]; + signed_size_type bytes_read = ::read(read_descriptor_, data, sizeof(data)); + if (bytes_read < 0 && errno == EINTR) + continue; + bool was_interrupted = (bytes_read > 0); + while (bytes_read == sizeof(data)) + bytes_read = ::read(read_descriptor_, data, sizeof(data)); + return was_interrupted; + } +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // !defined(BOOST_ASIO_HAS_EVENTFD) +#endif // !defined(__SYMBIAN32__) +#endif // !defined(__CYGWIN__) +#endif // !defined(BOOST_ASIO_WINDOWS) +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
diff --git a/boost/boost/asio/detail/impl/posix_event.ipp b/boost/boost/asio/detail/impl/posix_event.ipp new file mode 100644 index 0000000..9514972 --- /dev/null +++ b/boost/boost/asio/detail/impl/posix_event.ipp
@@ -0,0 +1,49 @@ +// +// detail/impl/posix_event.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_POSIX_EVENT_IPP +#define BOOST_ASIO_DETAIL_IMPL_POSIX_EVENT_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_HAS_PTHREADS) + +#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> + +namespace boost { +namespace asio { +namespace detail { + +posix_event::posix_event() + : state_(0) +{ + int error = ::pthread_cond_init(&cond_, 0); + boost::system::error_code ec(error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "event"); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_PTHREADS) + +#endif // BOOST_ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
diff --git a/boost/boost/asio/detail/impl/posix_mutex.ipp b/boost/boost/asio/detail/impl/posix_mutex.ipp new file mode 100644 index 0000000..e470cfa --- /dev/null +++ b/boost/boost/asio/detail/impl/posix_mutex.ipp
@@ -0,0 +1,48 @@ +// +// detail/impl/posix_mutex.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_POSIX_MUTEX_IPP +#define BOOST_ASIO_DETAIL_IMPL_POSIX_MUTEX_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_HAS_PTHREADS) + +#include <boost/asio/detail/posix_mutex.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +posix_mutex::posix_mutex() +{ + int error = ::pthread_mutex_init(&mutex_, 0); + boost::system::error_code ec(error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "mutex"); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_PTHREADS) + +#endif // BOOST_ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
diff --git a/boost/boost/asio/detail/impl/posix_thread.ipp b/boost/boost/asio/detail/impl/posix_thread.ipp new file mode 100644 index 0000000..5253cd9 --- /dev/null +++ b/boost/boost/asio/detail/impl/posix_thread.ipp
@@ -0,0 +1,76 @@ +// +// detail/impl/posix_thread.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_POSIX_THREAD_IPP +#define BOOST_ASIO_DETAIL_IMPL_POSIX_THREAD_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_HAS_PTHREADS) + +#include <boost/asio/detail/posix_thread.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +posix_thread::~posix_thread() +{ + if (!joined_) + ::pthread_detach(thread_); +} + +void posix_thread::join() +{ + if (!joined_) + { + ::pthread_join(thread_, 0); + joined_ = true; + } +} + +void posix_thread::start_thread(func_base* arg) +{ + int error = ::pthread_create(&thread_, 0, + boost_asio_detail_posix_thread_function, arg); + if (error != 0) + { + delete arg; + boost::system::error_code ec(error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "thread"); + } +} + +void* boost_asio_detail_posix_thread_function(void* arg) +{ + posix_thread::auto_func_base_ptr func = { + static_cast<posix_thread::func_base*>(arg) }; + func.ptr->run(); + return 0; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_PTHREADS) + +#endif // BOOST_ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
diff --git a/boost/boost/asio/detail/impl/posix_tss_ptr.ipp b/boost/boost/asio/detail/impl/posix_tss_ptr.ipp new file mode 100644 index 0000000..042b014 --- /dev/null +++ b/boost/boost/asio/detail/impl/posix_tss_ptr.ipp
@@ -0,0 +1,48 @@ +// +// detail/impl/posix_tss_ptr.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_POSIX_TSS_PTR_IPP +#define BOOST_ASIO_DETAIL_IMPL_POSIX_TSS_PTR_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_HAS_PTHREADS) + +#include <boost/asio/detail/posix_tss_ptr.hpp> +#include <boost/asio/detail/throw_error.hpp> +#include <boost/asio/error.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +void posix_tss_ptr_create(pthread_key_t& key) +{ + int error = ::pthread_key_create(&key, 0); + boost::system::error_code ec(error, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "tss"); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_PTHREADS) + +#endif // BOOST_ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
diff --git a/boost/boost/asio/detail/impl/reactive_descriptor_service.ipp b/boost/boost/asio/detail/impl/reactive_descriptor_service.ipp new file mode 100644 index 0000000..cf6547f --- /dev/null +++ b/boost/boost/asio/detail/impl/reactive_descriptor_service.ipp
@@ -0,0 +1,210 @@ +// +// detail/impl/reactive_descriptor_service.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_REACTIVE_DESCRIPTOR_SERVICE_IPP +#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_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_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + +#include <boost/asio/error.hpp> +#include <boost/asio/detail/reactive_descriptor_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +reactive_descriptor_service::reactive_descriptor_service( + boost::asio::io_service& io_service) + : reactor_(boost::asio::use_service<reactor>(io_service)) +{ + reactor_.init_task(); +} + +void reactive_descriptor_service::shutdown_service() +{ +} + +void reactive_descriptor_service::construct( + reactive_descriptor_service::implementation_type& impl) +{ + impl.descriptor_ = -1; + impl.state_ = 0; +} + +void reactive_descriptor_service::move_construct( + reactive_descriptor_service::implementation_type& impl, + reactive_descriptor_service::implementation_type& other_impl) +{ + impl.descriptor_ = other_impl.descriptor_; + other_impl.descriptor_ = -1; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + reactor_.move_descriptor(impl.descriptor_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_descriptor_service::move_assign( + reactive_descriptor_service::implementation_type& impl, + reactive_descriptor_service& other_service, + reactive_descriptor_service::implementation_type& other_impl) +{ + destroy(impl); + + impl.descriptor_ = other_impl.descriptor_; + other_impl.descriptor_ = -1; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + other_service.reactor_.move_descriptor(impl.descriptor_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_descriptor_service::destroy( + reactive_descriptor_service::implementation_type& impl) +{ + if (is_open(impl)) + { + BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "close")); + + reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, + (impl.state_ & descriptor_ops::possible_dup) == 0); + } + + boost::system::error_code ignored_ec; + descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec); +} + +boost::system::error_code reactive_descriptor_service::assign( + reactive_descriptor_service::implementation_type& impl, + const native_handle_type& native_descriptor, boost::system::error_code& ec) +{ + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (int err = reactor_.register_descriptor( + native_descriptor, impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.descriptor_ = native_descriptor; + impl.state_ = descriptor_ops::possible_dup; + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code reactive_descriptor_service::close( + reactive_descriptor_service::implementation_type& impl, + boost::system::error_code& ec) +{ + if (is_open(impl)) + { + BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "close")); + + reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, + (impl.state_ & descriptor_ops::possible_dup) == 0); + } + + descriptor_ops::close(impl.descriptor_, impl.state_, ec); + + // The descriptor is closed by the OS even if close() returns an error. + // + // (Actually, POSIX says the state of the descriptor is unspecified. On + // Linux the descriptor is apparently closed anyway; e.g. see + // http://lkml.org/lkml/2005/9/10/129 + // We'll just have to assume that other OSes follow the same behaviour.) + construct(impl); + + return ec; +} + +reactive_descriptor_service::native_handle_type +reactive_descriptor_service::release( + reactive_descriptor_service::implementation_type& impl) +{ + native_handle_type descriptor = impl.descriptor_; + + if (is_open(impl)) + { + BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "release")); + + reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, false); + construct(impl); + } + + return descriptor; +} + +boost::system::error_code reactive_descriptor_service::cancel( + reactive_descriptor_service::implementation_type& impl, + boost::system::error_code& ec) +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "cancel")); + + reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_); + ec = boost::system::error_code(); + return ec; +} + +void reactive_descriptor_service::start_op( + reactive_descriptor_service::implementation_type& impl, + int op_type, reactor_op* op, bool is_continuation, + bool is_non_blocking, bool noop) +{ + if (!noop) + { + if ((impl.state_ & descriptor_ops::non_blocking) || + descriptor_ops::set_internal_non_blocking( + impl.descriptor_, impl.state_, true, op->ec_)) + { + reactor_.start_op(op_type, impl.descriptor_, + impl.reactor_data_, op, is_continuation, is_non_blocking); + return; + } + } + + reactor_.post_immediate_completion(op, is_continuation); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) + +#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
diff --git a/boost/boost/asio/detail/impl/reactive_serial_port_service.ipp b/boost/boost/asio/detail/impl/reactive_serial_port_service.ipp new file mode 100644 index 0000000..d4f6157 --- /dev/null +++ b/boost/boost/asio/detail/impl/reactive_serial_port_service.ipp
@@ -0,0 +1,153 @@ +// +// detail/impl/reactive_serial_port_service.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP +#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_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_HAS_SERIAL_PORT) +#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) + +#include <cstring> +#include <boost/asio/detail/reactive_serial_port_service.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +reactive_serial_port_service::reactive_serial_port_service( + boost::asio::io_service& io_service) + : descriptor_service_(io_service) +{ +} + +void reactive_serial_port_service::shutdown_service() +{ + descriptor_service_.shutdown_service(); +} + +boost::system::error_code reactive_serial_port_service::open( + reactive_serial_port_service::implementation_type& impl, + const std::string& device, boost::system::error_code& ec) +{ + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + descriptor_ops::state_type state = 0; + int fd = descriptor_ops::open(device.c_str(), + O_RDWR | O_NONBLOCK | O_NOCTTY, ec); + if (fd < 0) + return ec; + + int s = descriptor_ops::fcntl(fd, F_GETFL, ec); + if (s >= 0) + s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec); + if (s < 0) + { + boost::system::error_code ignored_ec; + descriptor_ops::close(fd, state, ignored_ec); + return ec; + } + + // Set up default serial port options. + termios ios; + errno = 0; + s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec); + if (s >= 0) + { +#if defined(_BSD_SOURCE) + ::cfmakeraw(&ios); +#else + ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK + | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + ios.c_oflag &= ~OPOST; + ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + ios.c_cflag &= ~(CSIZE | PARENB); + ios.c_cflag |= CS8; +#endif + ios.c_iflag |= IGNPAR; + ios.c_cflag |= CREAD | CLOCAL; + errno = 0; + s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec); + } + if (s < 0) + { + boost::system::error_code ignored_ec; + descriptor_ops::close(fd, state, ignored_ec); + return ec; + } + + // We're done. Take ownership of the serial port descriptor. + if (descriptor_service_.assign(impl, fd, ec)) + { + boost::system::error_code ignored_ec; + descriptor_ops::close(fd, state, ignored_ec); + } + + return ec; +} + +boost::system::error_code reactive_serial_port_service::do_set_option( + reactive_serial_port_service::implementation_type& impl, + reactive_serial_port_service::store_function_type store, + const void* option, boost::system::error_code& ec) +{ + termios ios; + errno = 0; + descriptor_ops::error_wrapper(::tcgetattr( + descriptor_service_.native_handle(impl), &ios), ec); + if (ec) + return ec; + + if (store(option, ios, ec)) + return ec; + + errno = 0; + descriptor_ops::error_wrapper(::tcsetattr( + descriptor_service_.native_handle(impl), TCSANOW, &ios), ec); + return ec; +} + +boost::system::error_code reactive_serial_port_service::do_get_option( + const reactive_serial_port_service::implementation_type& impl, + reactive_serial_port_service::load_function_type load, + void* option, boost::system::error_code& ec) const +{ + termios ios; + errno = 0; + descriptor_ops::error_wrapper(::tcgetattr( + descriptor_service_.native_handle(impl), &ios), ec); + if (ec) + return ec; + + return load(option, ios, ec); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) +#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT) + +#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
diff --git a/boost/boost/asio/detail/impl/reactive_socket_service_base.ipp b/boost/boost/asio/detail/impl/reactive_socket_service_base.ipp new file mode 100644 index 0000000..2ef23a1 --- /dev/null +++ b/boost/boost/asio/detail/impl/reactive_socket_service_base.ipp
@@ -0,0 +1,269 @@ +// +// detail/reactive_socket_service_base.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_REACTIVE_SOCKET_SERVICE_BASE_IPP +#define BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_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_HAS_IOCP) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#include <boost/asio/detail/reactive_socket_service_base.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +reactive_socket_service_base::reactive_socket_service_base( + boost::asio::io_service& io_service) + : reactor_(use_service<reactor>(io_service)) +{ + reactor_.init_task(); +} + +void reactive_socket_service_base::shutdown_service() +{ +} + +void reactive_socket_service_base::construct( + reactive_socket_service_base::base_implementation_type& impl) +{ + impl.socket_ = invalid_socket; + impl.state_ = 0; +} + +void reactive_socket_service_base::base_move_construct( + reactive_socket_service_base::base_implementation_type& impl, + reactive_socket_service_base::base_implementation_type& other_impl) +{ + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + reactor_.move_descriptor(impl.socket_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_socket_service_base::base_move_assign( + reactive_socket_service_base::base_implementation_type& impl, + reactive_socket_service_base& other_service, + reactive_socket_service_base::base_implementation_type& other_impl) +{ + destroy(impl); + + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + other_service.reactor_.move_descriptor(impl.socket_, + impl.reactor_data_, other_impl.reactor_data_); +} + +void reactive_socket_service_base::destroy( + reactive_socket_service_base::base_implementation_type& impl) +{ + if (impl.socket_ != invalid_socket) + { + BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, + (impl.state_ & socket_ops::possible_dup) == 0); + + boost::system::error_code ignored_ec; + socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); + } +} + +boost::system::error_code reactive_socket_service_base::close( + reactive_socket_service_base::base_implementation_type& impl, + boost::system::error_code& ec) +{ + if (is_open(impl)) + { + BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close")); + + reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, + (impl.state_ & socket_ops::possible_dup) == 0); + } + + socket_ops::close(impl.socket_, impl.state_, false, ec); + + // The descriptor is closed by the OS even if close() returns an error. + // + // (Actually, POSIX says the state of the descriptor is unspecified. On + // Linux the descriptor is apparently closed anyway; e.g. see + // http://lkml.org/lkml/2005/9/10/129 + // We'll just have to assume that other OSes follow the same behaviour. The + // known exception is when Windows's closesocket() function fails with + // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close(). + construct(impl); + + return ec; +} + +boost::system::error_code reactive_socket_service_base::cancel( + reactive_socket_service_base::base_implementation_type& impl, + boost::system::error_code& ec) +{ + if (!is_open(impl)) + { + ec = boost::asio::error::bad_descriptor; + return ec; + } + + BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "cancel")); + + reactor_.cancel_ops(impl.socket_, impl.reactor_data_); + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code reactive_socket_service_base::do_open( + reactive_socket_service_base::base_implementation_type& impl, + int af, int type, int protocol, boost::system::error_code& ec) +{ + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + socket_holder sock(socket_ops::socket(af, type, protocol, ec)); + if (sock.get() == invalid_socket) + return ec; + + if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.socket_ = sock.release(); + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code reactive_socket_service_base::do_assign( + reactive_socket_service_base::base_implementation_type& impl, int type, + const reactive_socket_service_base::native_handle_type& native_socket, + boost::system::error_code& ec) +{ + if (is_open(impl)) + { + ec = boost::asio::error::already_open; + return ec; + } + + if (int err = reactor_.register_descriptor( + native_socket, impl.reactor_data_)) + { + ec = boost::system::error_code(err, + boost::asio::error::get_system_category()); + return ec; + } + + impl.socket_ = native_socket; + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + impl.state_ |= socket_ops::possible_dup; + ec = boost::system::error_code(); + return ec; +} + +void reactive_socket_service_base::start_op( + reactive_socket_service_base::base_implementation_type& impl, + int op_type, reactor_op* op, bool is_continuation, + bool is_non_blocking, bool noop) +{ + if (!noop) + { + if ((impl.state_ & socket_ops::non_blocking) + || socket_ops::set_internal_non_blocking( + impl.socket_, impl.state_, true, op->ec_)) + { + reactor_.start_op(op_type, impl.socket_, + impl.reactor_data_, op, is_continuation, is_non_blocking); + return; + } + } + + reactor_.post_immediate_completion(op, is_continuation); +} + +void reactive_socket_service_base::start_accept_op( + reactive_socket_service_base::base_implementation_type& impl, + reactor_op* op, bool is_continuation, bool peer_is_open) +{ + if (!peer_is_open) + start_op(impl, reactor::read_op, op, true, is_continuation, false); + else + { + op->ec_ = boost::asio::error::already_open; + reactor_.post_immediate_completion(op, is_continuation); + } +} + +void reactive_socket_service_base::start_connect_op( + reactive_socket_service_base::base_implementation_type& impl, + reactor_op* op, bool is_continuation, + const socket_addr_type* addr, size_t addrlen) +{ + if ((impl.state_ & socket_ops::non_blocking) + || socket_ops::set_internal_non_blocking( + impl.socket_, impl.state_, true, op->ec_)) + { + if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0) + { + if (op->ec_ == boost::asio::error::in_progress + || op->ec_ == boost::asio::error::would_block) + { + op->ec_ = boost::system::error_code(); + reactor_.start_op(reactor::connect_op, impl.socket_, + impl.reactor_data_, op, is_continuation, false); + return; + } + } + } + + reactor_.post_immediate_completion(op, is_continuation); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // !defined(BOOST_ASIO_HAS_IOCP) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#endif // BOOST_ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
diff --git a/boost/boost/asio/detail/impl/resolver_service_base.ipp b/boost/boost/asio/detail/impl/resolver_service_base.ipp new file mode 100644 index 0000000..484aead --- /dev/null +++ b/boost/boost/asio/detail/impl/resolver_service_base.ipp
@@ -0,0 +1,132 @@ +// +// detail/impl/resolver_service_base.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_RESOLVER_SERVICE_BASE_IPP +#define BOOST_ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_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/resolver_service_base.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +class resolver_service_base::work_io_service_runner +{ +public: + work_io_service_runner(boost::asio::io_service& io_service) + : io_service_(io_service) {} + void operator()() { io_service_.run(); } +private: + boost::asio::io_service& io_service_; +}; + +resolver_service_base::resolver_service_base( + boost::asio::io_service& io_service) + : io_service_impl_(boost::asio::use_service<io_service_impl>(io_service)), + work_io_service_(new boost::asio::io_service), + work_io_service_impl_(boost::asio::use_service< + io_service_impl>(*work_io_service_)), + work_(new boost::asio::io_service::work(*work_io_service_)), + work_thread_(0) +{ +} + +resolver_service_base::~resolver_service_base() +{ + shutdown_service(); +} + +void resolver_service_base::shutdown_service() +{ + work_.reset(); + if (work_io_service_.get()) + { + work_io_service_->stop(); + if (work_thread_.get()) + { + work_thread_->join(); + work_thread_.reset(); + } + work_io_service_.reset(); + } +} + +void resolver_service_base::fork_service( + boost::asio::io_service::fork_event fork_ev) +{ + if (work_thread_.get()) + { + if (fork_ev == boost::asio::io_service::fork_prepare) + { + work_io_service_->stop(); + work_thread_->join(); + } + else + { + work_io_service_->reset(); + work_thread_.reset(new boost::asio::detail::thread( + work_io_service_runner(*work_io_service_))); + } + } +} + +void resolver_service_base::construct( + resolver_service_base::implementation_type& impl) +{ + impl.reset(static_cast<void*>(0), socket_ops::noop_deleter()); +} + +void resolver_service_base::destroy( + resolver_service_base::implementation_type& impl) +{ + BOOST_ASIO_HANDLER_OPERATION(("resolver", &impl, "cancel")); + + impl.reset(); +} + +void resolver_service_base::cancel( + resolver_service_base::implementation_type& impl) +{ + BOOST_ASIO_HANDLER_OPERATION(("resolver", &impl, "cancel")); + + impl.reset(static_cast<void*>(0), socket_ops::noop_deleter()); +} + +void resolver_service_base::start_resolve_op(operation* op) +{ + start_work_thread(); + io_service_impl_.work_started(); + work_io_service_impl_.post_immediate_completion(op, false); +} + +void resolver_service_base::start_work_thread() +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + if (!work_thread_.get()) + { + work_thread_.reset(new boost::asio::detail::thread( + work_io_service_runner(*work_io_service_))); + } +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
diff --git a/boost/boost/asio/detail/impl/select_reactor.hpp b/boost/boost/asio/detail/impl/select_reactor.hpp new file mode 100644 index 0000000..4461681 --- /dev/null +++ b/boost/boost/asio/detail/impl/select_reactor.hpp
@@ -0,0 +1,89 @@ +// +// detail/impl/select_reactor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_SELECT_REACTOR_HPP +#define BOOST_ASIO_DETAIL_IMPL_SELECT_REACTOR_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_IOCP) \ + || (!defined(BOOST_ASIO_HAS_DEV_POLL) \ + && !defined(BOOST_ASIO_HAS_EPOLL) \ + && !defined(BOOST_ASIO_HAS_KQUEUE) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Time_Traits> +void select_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_add_timer_queue(queue); +} + +// Remove a timer queue from the reactor. +template <typename Time_Traits> +void select_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_remove_timer_queue(queue); +} + +template <typename Time_Traits> +void select_reactor::schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + io_service_.post_immediate_completion(op, false); + return; + } + + bool earliest = queue.enqueue_timer(time, timer, op); + io_service_.work_started(); + if (earliest) + interrupter_.interrupt(); +} + +template <typename Time_Traits> +std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + std::size_t n = queue.cancel_timer(timer, ops, max_cancelled); + lock.unlock(); + io_service_.post_deferred_completions(ops); + return n; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_IOCP) + // || (!defined(BOOST_ASIO_HAS_DEV_POLL) + // && !defined(BOOST_ASIO_HAS_EPOLL) + // && !defined(BOOST_ASIO_HAS_KQUEUE) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) + +#endif // BOOST_ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
diff --git a/boost/boost/asio/detail/impl/select_reactor.ipp b/boost/boost/asio/detail/impl/select_reactor.ipp new file mode 100644 index 0000000..9269f94 --- /dev/null +++ b/boost/boost/asio/detail/impl/select_reactor.ipp
@@ -0,0 +1,315 @@ +// +// detail/impl/select_reactor.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_SELECT_REACTOR_IPP +#define BOOST_ASIO_DETAIL_IMPL_SELECT_REACTOR_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_HAS_IOCP) \ + || (!defined(BOOST_ASIO_HAS_DEV_POLL) \ + && !defined(BOOST_ASIO_HAS_EPOLL) \ + && !defined(BOOST_ASIO_HAS_KQUEUE) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) + +#include <boost/asio/detail/bind_handler.hpp> +#include <boost/asio/detail/fd_set_adapter.hpp> +#include <boost/asio/detail/select_reactor.hpp> +#include <boost/asio/detail/signal_blocker.hpp> +#include <boost/asio/detail/socket_ops.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +select_reactor::select_reactor(boost::asio::io_service& io_service) + : boost::asio::detail::service_base<select_reactor>(io_service), + io_service_(use_service<io_service_impl>(io_service)), + mutex_(), + interrupter_(), +#if defined(BOOST_ASIO_HAS_IOCP) + stop_thread_(false), + thread_(0), +#endif // defined(BOOST_ASIO_HAS_IOCP) + shutdown_(false) +{ +#if defined(BOOST_ASIO_HAS_IOCP) + boost::asio::detail::signal_blocker sb; + thread_ = new boost::asio::detail::thread( + bind_handler(&select_reactor::call_run_thread, this)); +#endif // defined(BOOST_ASIO_HAS_IOCP) +} + +select_reactor::~select_reactor() +{ + shutdown_service(); +} + +void select_reactor::shutdown_service() +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + shutdown_ = true; +#if defined(BOOST_ASIO_HAS_IOCP) + stop_thread_ = true; +#endif // defined(BOOST_ASIO_HAS_IOCP) + lock.unlock(); + +#if defined(BOOST_ASIO_HAS_IOCP) + if (thread_) + { + interrupter_.interrupt(); + thread_->join(); + delete thread_; + thread_ = 0; + } +#endif // defined(BOOST_ASIO_HAS_IOCP) + + op_queue<operation> ops; + + for (int i = 0; i < max_ops; ++i) + op_queue_[i].get_all_operations(ops); + + timer_queues_.get_all_timers(ops); + + io_service_.abandon_operations(ops); +} + +void select_reactor::fork_service(boost::asio::io_service::fork_event fork_ev) +{ + if (fork_ev == boost::asio::io_service::fork_child) + interrupter_.recreate(); +} + +void select_reactor::init_task() +{ + io_service_.init_task(); +} + +int select_reactor::register_descriptor(socket_type, + select_reactor::per_descriptor_data&) +{ + return 0; +} + +int select_reactor::register_internal_descriptor( + int op_type, socket_type descriptor, + select_reactor::per_descriptor_data&, reactor_op* op) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + op_queue_[op_type].enqueue_operation(descriptor, op); + interrupter_.interrupt(); + + return 0; +} + +void select_reactor::move_descriptor(socket_type, + select_reactor::per_descriptor_data&, + select_reactor::per_descriptor_data&) +{ +} + +void select_reactor::start_op(int op_type, socket_type descriptor, + select_reactor::per_descriptor_data&, reactor_op* op, + bool is_continuation, bool) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + post_immediate_completion(op, is_continuation); + return; + } + + bool first = op_queue_[op_type].enqueue_operation(descriptor, op); + io_service_.work_started(); + if (first) + interrupter_.interrupt(); +} + +void select_reactor::cancel_ops(socket_type descriptor, + select_reactor::per_descriptor_data&) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted); +} + +void select_reactor::deregister_descriptor(socket_type descriptor, + select_reactor::per_descriptor_data&, bool) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + cancel_ops_unlocked(descriptor, boost::asio::error::operation_aborted); +} + +void select_reactor::deregister_internal_descriptor( + socket_type descriptor, select_reactor::per_descriptor_data&) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + op_queue_[i].cancel_operations(descriptor, ops); +} + +void select_reactor::run(bool block, op_queue<operation>& ops) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + +#if defined(BOOST_ASIO_HAS_IOCP) + // Check if the thread is supposed to stop. + if (stop_thread_) + return; +#endif // defined(BOOST_ASIO_HAS_IOCP) + + // Set up the descriptor sets. + for (int i = 0; i < max_select_ops; ++i) + fd_sets_[i].reset(); + fd_sets_[read_op].set(interrupter_.read_descriptor()); + socket_type max_fd = 0; + bool have_work_to_do = !timer_queues_.all_empty(); + for (int i = 0; i < max_select_ops; ++i) + { + have_work_to_do = have_work_to_do || !op_queue_[i].empty(); + fd_sets_[i].set(op_queue_[i], ops); + if (fd_sets_[i].max_descriptor() > max_fd) + max_fd = fd_sets_[i].max_descriptor(); + } + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // Connection operations on Windows use both except and write fd_sets. + have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty(); + fd_sets_[write_op].set(op_queue_[connect_op], ops); + if (fd_sets_[write_op].max_descriptor() > max_fd) + max_fd = fd_sets_[write_op].max_descriptor(); + fd_sets_[except_op].set(op_queue_[connect_op], ops); + if (fd_sets_[except_op].max_descriptor() > max_fd) + max_fd = fd_sets_[except_op].max_descriptor(); +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + + // We can return immediately if there's no work to do and the reactor is + // not supposed to block. + if (!block && !have_work_to_do) + return; + + // Determine how long to block while waiting for events. + timeval tv_buf = { 0, 0 }; + timeval* tv = block ? get_timeout(tv_buf) : &tv_buf; + + lock.unlock(); + + // Block on the select call until descriptors become ready. + boost::system::error_code ec; + int retval = socket_ops::select(static_cast<int>(max_fd + 1), + fd_sets_[read_op], fd_sets_[write_op], fd_sets_[except_op], tv, ec); + + // Reset the interrupter. + if (retval > 0 && fd_sets_[read_op].is_set(interrupter_.read_descriptor())) + { + interrupter_.reset(); + --retval; + } + + lock.lock(); + + // Dispatch all ready operations. + if (retval > 0) + { +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // Connection operations on Windows use both except and write fd_sets. + fd_sets_[except_op].perform(op_queue_[connect_op], ops); + fd_sets_[write_op].perform(op_queue_[connect_op], ops); +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + + // Exception operations must be processed first to ensure that any + // out-of-band data is read before normal data. + for (int i = max_select_ops - 1; i >= 0; --i) + fd_sets_[i].perform(op_queue_[i], ops); + } + timer_queues_.get_ready_timers(ops); +} + +void select_reactor::interrupt() +{ + interrupter_.interrupt(); +} + +#if defined(BOOST_ASIO_HAS_IOCP) +void select_reactor::run_thread() +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + while (!stop_thread_) + { + lock.unlock(); + op_queue<operation> ops; + run(true, ops); + io_service_.post_deferred_completions(ops); + lock.lock(); + } +} + +void select_reactor::call_run_thread(select_reactor* reactor) +{ + reactor->run_thread(); +} +#endif // defined(BOOST_ASIO_HAS_IOCP) + +void select_reactor::do_add_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.insert(&queue); +} + +void select_reactor::do_remove_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.erase(&queue); +} + +timeval* select_reactor::get_timeout(timeval& tv) +{ + // By default we will wait no longer than 5 minutes. This will ensure that + // any changes to the system clock are detected after no longer than this. + long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000); + tv.tv_sec = usec / 1000000; + tv.tv_usec = usec % 1000000; + return &tv; +} + +void select_reactor::cancel_ops_unlocked(socket_type descriptor, + const boost::system::error_code& ec) +{ + bool need_interrupt = false; + op_queue<operation> ops; + for (int i = 0; i < max_ops; ++i) + need_interrupt = op_queue_[i].cancel_operations( + descriptor, ops, ec) || need_interrupt; + io_service_.post_deferred_completions(ops); + if (need_interrupt) + interrupter_.interrupt(); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // defined(BOOST_ASIO_HAS_IOCP) + // || (!defined(BOOST_ASIO_HAS_DEV_POLL) + // && !defined(BOOST_ASIO_HAS_EPOLL) + // && !defined(BOOST_ASIO_HAS_KQUEUE)) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME)) + +#endif // BOOST_ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
diff --git a/boost/boost/asio/detail/impl/service_registry.hpp b/boost/boost/asio/detail/impl/service_registry.hpp new file mode 100644 index 0000000..9e0a8b4 --- /dev/null +++ b/boost/boost/asio/detail/impl/service_registry.hpp
@@ -0,0 +1,90 @@ +// +// detail/impl/service_registry.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_SERVICE_REGISTRY_HPP +#define BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +template <typename Service, typename Arg> +service_registry::service_registry( + boost::asio::io_service& o, Service*, Arg arg) + : owner_(o), + first_service_(new Service(o, arg)) +{ + boost::asio::io_service::service::key key; + init_key(key, Service::id); + first_service_->key_ = key; + first_service_->next_ = 0; +} + +template <typename Service> +Service& service_registry::first_service() +{ + return *static_cast<Service*>(first_service_); +} + +template <typename Service> +Service& service_registry::use_service() +{ + boost::asio::io_service::service::key key; + init_key(key, Service::id); + factory_type factory = &service_registry::create<Service>; + return *static_cast<Service*>(do_use_service(key, factory)); +} + +template <typename Service> +void service_registry::add_service(Service* new_service) +{ + boost::asio::io_service::service::key key; + init_key(key, Service::id); + return do_add_service(key, new_service); +} + +template <typename Service> +bool service_registry::has_service() const +{ + boost::asio::io_service::service::key key; + init_key(key, Service::id); + return do_has_service(key); +} + +#if !defined(BOOST_ASIO_NO_TYPEID) +template <typename Service> +void service_registry::init_key(boost::asio::io_service::service::key& key, + const boost::asio::detail::service_id<Service>& /*id*/) +{ + key.type_info_ = &typeid(typeid_wrapper<Service>); + key.id_ = 0; +} +#endif // !defined(BOOST_ASIO_NO_TYPEID) + +template <typename Service> +boost::asio::io_service::service* service_registry::create( + boost::asio::io_service& owner) +{ + return new Service(owner); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
diff --git a/boost/boost/asio/detail/impl/service_registry.ipp b/boost/boost/asio/detail/impl/service_registry.ipp new file mode 100644 index 0000000..00deec9 --- /dev/null +++ b/boost/boost/asio/detail/impl/service_registry.ipp
@@ -0,0 +1,190 @@ +// +// detail/impl/service_registry.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_SERVICE_REGISTRY_IPP +#define BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> +#include <vector> +#include <boost/asio/detail/service_registry.hpp> +#include <boost/asio/detail/throw_exception.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +service_registry::~service_registry() +{ + // Shutdown all services. This must be done in a separate loop before the + // services are destroyed since the destructors of user-defined handler + // objects may try to access other service objects. + boost::asio::io_service::service* service = first_service_; + while (service) + { + service->shutdown_service(); + service = service->next_; + } + + // Destroy all services. + while (first_service_) + { + boost::asio::io_service::service* next_service = first_service_->next_; + destroy(first_service_); + first_service_ = next_service; + } +} + +void service_registry::notify_fork(boost::asio::io_service::fork_event fork_ev) +{ + // Make a copy of all of the services while holding the lock. We don't want + // to hold the lock while calling into each service, as it may try to call + // back into this class. + std::vector<boost::asio::io_service::service*> services; + { + boost::asio::detail::mutex::scoped_lock lock(mutex_); + boost::asio::io_service::service* service = first_service_; + while (service) + { + services.push_back(service); + service = service->next_; + } + } + + // If processing the fork_prepare event, we want to go in reverse order of + // service registration, which happens to be the existing order of the + // services in the vector. For the other events we want to go in the other + // direction. + std::size_t num_services = services.size(); + if (fork_ev == boost::asio::io_service::fork_prepare) + for (std::size_t i = 0; i < num_services; ++i) + services[i]->fork_service(fork_ev); + else + for (std::size_t i = num_services; i > 0; --i) + services[i - 1]->fork_service(fork_ev); +} + +void service_registry::init_key(boost::asio::io_service::service::key& key, + const boost::asio::io_service::id& id) +{ + key.type_info_ = 0; + key.id_ = &id; +} + +bool service_registry::keys_match( + const boost::asio::io_service::service::key& key1, + const boost::asio::io_service::service::key& key2) +{ + if (key1.id_ && key2.id_) + if (key1.id_ == key2.id_) + return true; + if (key1.type_info_ && key2.type_info_) + if (*key1.type_info_ == *key2.type_info_) + return true; + return false; +} + +void service_registry::destroy(boost::asio::io_service::service* service) +{ + delete service; +} + +boost::asio::io_service::service* service_registry::do_use_service( + const boost::asio::io_service::service::key& key, + factory_type factory) +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // First see if there is an existing service object with the given key. + boost::asio::io_service::service* service = first_service_; + while (service) + { + if (keys_match(service->key_, key)) + return service; + service = service->next_; + } + + // Create a new service object. The service registry's mutex is not locked + // at this time to allow for nested calls into this function from the new + // service's constructor. + lock.unlock(); + auto_service_ptr new_service = { factory(owner_) }; + new_service.ptr_->key_ = key; + lock.lock(); + + // Check that nobody else created another service object of the same type + // while the lock was released. + service = first_service_; + while (service) + { + if (keys_match(service->key_, key)) + return service; + service = service->next_; + } + + // Service was successfully initialised, pass ownership to registry. + new_service.ptr_->next_ = first_service_; + first_service_ = new_service.ptr_; + new_service.ptr_ = 0; + return first_service_; +} + +void service_registry::do_add_service( + const boost::asio::io_service::service::key& key, + boost::asio::io_service::service* new_service) +{ + if (&owner_ != &new_service->get_io_service()) + boost::asio::detail::throw_exception(invalid_service_owner()); + + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + // Check if there is an existing service object with the given key. + boost::asio::io_service::service* service = first_service_; + while (service) + { + if (keys_match(service->key_, key)) + boost::asio::detail::throw_exception(service_already_exists()); + service = service->next_; + } + + // Take ownership of the service object. + new_service->key_ = key; + new_service->next_ = first_service_; + first_service_ = new_service; +} + +bool service_registry::do_has_service( + const boost::asio::io_service::service::key& key) const +{ + boost::asio::detail::mutex::scoped_lock lock(mutex_); + + boost::asio::io_service::service* service = first_service_; + while (service) + { + if (keys_match(service->key_, key)) + return true; + service = service->next_; + } + + return false; +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
diff --git a/boost/boost/asio/detail/impl/signal_set_service.ipp b/boost/boost/asio/detail/impl/signal_set_service.ipp new file mode 100644 index 0000000..8fde0a8 --- /dev/null +++ b/boost/boost/asio/detail/impl/signal_set_service.ipp
@@ -0,0 +1,649 @@ +// +// detail/impl/signal_set_service.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 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_SIGNAL_SET_SERVICE_IPP +#define BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#include <cstring> +#include <boost/asio/detail/reactor.hpp> +#include <boost/asio/detail/signal_blocker.hpp> +#include <boost/asio/detail/signal_set_service.hpp> +#include <boost/asio/detail/static_mutex.hpp> + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { + +struct signal_state +{ + // Mutex used for protecting global state. + static_mutex mutex_; + + // The read end of the pipe used for signal notifications. + int read_descriptor_; + + // The write end of the pipe used for signal notifications. + int write_descriptor_; + + // Whether the signal state has been prepared for a fork. + bool fork_prepared_; + + // The head of a linked list of all signal_set_service instances. + class signal_set_service* service_list_; + + // A count of the number of objects that are registered for each signal. + std::size_t registration_count_[max_signal_number]; +}; + +signal_state* get_signal_state() +{ + static signal_state state = { + BOOST_ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, { 0 } }; + return &state; +} + +void boost_asio_signal_handler(int signal_number) +{ +#if defined(BOOST_ASIO_WINDOWS) \ + || defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + || defined(__CYGWIN__) + signal_set_service::deliver_signal(signal_number); +#else // defined(BOOST_ASIO_WINDOWS) + // || defined(BOOST_ASIO_WINDOWS_RUNTIME) + // || defined(__CYGWIN__) + int saved_errno = errno; + signal_state* state = get_signal_state(); + signed_size_type result = ::write(state->write_descriptor_, + &signal_number, sizeof(signal_number)); + (void)result; + errno = saved_errno; +#endif // defined(BOOST_ASIO_WINDOWS) + // || defined(BOOST_ASIO_WINDOWS_RUNTIME) + // || defined(__CYGWIN__) + +#if defined(BOOST_ASIO_HAS_SIGNAL) && !defined(BOOST_ASIO_HAS_SIGACTION) + ::signal(signal_number, boost_asio_signal_handler); +#endif // defined(BOOST_ASIO_HAS_SIGNAL) && !defined(BOOST_ASIO_HAS_SIGACTION) +} + +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) +class signal_set_service::pipe_read_op : public reactor_op +{ +public: + pipe_read_op() + : reactor_op(&pipe_read_op::do_perform, pipe_read_op::do_complete) + { + } + + static bool do_perform(reactor_op*) + { + signal_state* state = get_signal_state(); + + int fd = state->read_descriptor_; + int signal_number = 0; + while (::read(fd, &signal_number, sizeof(int)) == sizeof(int)) + if (signal_number >= 0 && signal_number < max_signal_number) + signal_set_service::deliver_signal(signal_number); + + return false; + } + + static void do_complete(io_service_impl* /*owner*/, operation* base, + const boost::system::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + pipe_read_op* o(static_cast<pipe_read_op*>(base)); + delete o; + } +}; +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) + +signal_set_service::signal_set_service( + boost::asio::io_service& io_service) + : io_service_(boost::asio::use_service<io_service_impl>(io_service)), +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + reactor_(boost::asio::use_service<reactor>(io_service)), +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) + next_(0), + prev_(0) +{ + get_signal_state()->mutex_.init(); + +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + reactor_.init_task(); +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) + + for (int i = 0; i < max_signal_number; ++i) + registrations_[i] = 0; + + add_service(this); +} + +signal_set_service::~signal_set_service() +{ + remove_service(this); +} + +void signal_set_service::shutdown_service() +{ + remove_service(this); + + op_queue<operation> ops; + + for (int i = 0; i < max_signal_number; ++i) + { + registration* reg = registrations_[i]; + while (reg) + { + ops.push(*reg->queue_); + reg = reg->next_in_table_; + } + } + + io_service_.abandon_operations(ops); +} + +void signal_set_service::fork_service( + boost::asio::io_service::fork_event fork_ev) +{ +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + + switch (fork_ev) + { + case boost::asio::io_service::fork_prepare: + { + int read_descriptor = state->read_descriptor_; + state->fork_prepared_ = true; + lock.unlock(); + reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_); + } + break; + case boost::asio::io_service::fork_parent: + if (state->fork_prepared_) + { + int read_descriptor = state->read_descriptor_; + state->fork_prepared_ = false; + lock.unlock(); + reactor_.register_internal_descriptor(reactor::read_op, + read_descriptor, reactor_data_, new pipe_read_op); + } + break; + case boost::asio::io_service::fork_child: + if (state->fork_prepared_) + { + boost::asio::detail::signal_blocker blocker; + close_descriptors(); + open_descriptors(); + int read_descriptor = state->read_descriptor_; + state->fork_prepared_ = false; + lock.unlock(); + reactor_.register_internal_descriptor(reactor::read_op, + read_descriptor, reactor_data_, new pipe_read_op); + } + break; + default: + break; + } +#else // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) + (void)fork_ev; +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +} + +void signal_set_service::construct( + signal_set_service::implementation_type& impl) +{ + impl.signals_ = 0; +} + +void signal_set_service::destroy( + signal_set_service::implementation_type& impl) +{ + boost::system::error_code ignored_ec; + clear(impl, ignored_ec); + cancel(impl, ignored_ec); +} + +boost::system::error_code signal_set_service::add( + signal_set_service::implementation_type& impl, + int signal_number, boost::system::error_code& ec) +{ + // Check that the signal number is valid. + if (signal_number < 0 || signal_number >= max_signal_number) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + + // Find the appropriate place to insert the registration. + registration** insertion_point = &impl.signals_; + registration* next = impl.signals_; + while (next && next->signal_number_ < signal_number) + { + insertion_point = &next->next_in_set_; + next = next->next_in_set_; + } + + // Only do something if the signal is not already registered. + if (next == 0 || next->signal_number_ != signal_number) + { + registration* new_registration = new registration; + +#if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION) + // Register for the signal if we're the first. + if (state->registration_count_[signal_number] == 0) + { +# if defined(BOOST_ASIO_HAS_SIGACTION) + using namespace std; // For memset. + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = boost_asio_signal_handler; + sigfillset(&sa.sa_mask); + if (::sigaction(signal_number, &sa, 0) == -1) +# else // defined(BOOST_ASIO_HAS_SIGACTION) + if (::signal(signal_number, boost_asio_signal_handler) == SIG_ERR) +# endif // defined(BOOST_ASIO_HAS_SIGACTION) + { +# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ec = boost::asio::error::invalid_argument; +# else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); +# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + delete new_registration; + return ec; + } + } +#endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION) + + // Record the new registration in the set. + new_registration->signal_number_ = signal_number; + new_registration->queue_ = &impl.queue_; + new_registration->next_in_set_ = next; + *insertion_point = new_registration; + + // Insert registration into the registration table. + new_registration->next_in_table_ = registrations_[signal_number]; + if (registrations_[signal_number]) + registrations_[signal_number]->prev_in_table_ = new_registration; + registrations_[signal_number] = new_registration; + + ++state->registration_count_[signal_number]; + } + + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code signal_set_service::remove( + signal_set_service::implementation_type& impl, + int signal_number, boost::system::error_code& ec) +{ + // Check that the signal number is valid. + if (signal_number < 0 || signal_number >= max_signal_number) + { + ec = boost::asio::error::invalid_argument; + return ec; + } + + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + + // Find the signal number in the list of registrations. + registration** deletion_point = &impl.signals_; + registration* reg = impl.signals_; + while (reg && reg->signal_number_ < signal_number) + { + deletion_point = ®->next_in_set_; + reg = reg->next_in_set_; + } + + if (reg != 0 && reg->signal_number_ == signal_number) + { +#if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION) + // Set signal handler back to the default if we're the last. + if (state->registration_count_[signal_number] == 1) + { +# if defined(BOOST_ASIO_HAS_SIGACTION) + using namespace std; // For memset. + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + if (::sigaction(signal_number, &sa, 0) == -1) +# else // defined(BOOST_ASIO_HAS_SIGACTION) + if (::signal(signal_number, SIG_DFL) == SIG_ERR) +# endif // defined(BOOST_ASIO_HAS_SIGACTION) + { +# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ec = boost::asio::error::invalid_argument; +# else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); +# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + return ec; + } + } +#endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION) + + // Remove the registration from the set. + *deletion_point = reg->next_in_set_; + + // Remove the registration from the registration table. + if (registrations_[signal_number] == reg) + registrations_[signal_number] = reg->next_in_table_; + if (reg->prev_in_table_) + reg->prev_in_table_->next_in_table_ = reg->next_in_table_; + if (reg->next_in_table_) + reg->next_in_table_->prev_in_table_ = reg->prev_in_table_; + + --state->registration_count_[signal_number]; + + delete reg; + } + + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code signal_set_service::clear( + signal_set_service::implementation_type& impl, + boost::system::error_code& ec) +{ + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + + while (registration* reg = impl.signals_) + { +#if defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION) + // Set signal handler back to the default if we're the last. + if (state->registration_count_[reg->signal_number_] == 1) + { +# if defined(BOOST_ASIO_HAS_SIGACTION) + using namespace std; // For memset. + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + if (::sigaction(reg->signal_number_, &sa, 0) == -1) +# else // defined(BOOST_ASIO_HAS_SIGACTION) + if (::signal(reg->signal_number_, SIG_DFL) == SIG_ERR) +# endif // defined(BOOST_ASIO_HAS_SIGACTION) + { +# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ec = boost::asio::error::invalid_argument; +# else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); +# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + return ec; + } + } +#endif // defined(BOOST_ASIO_HAS_SIGNAL) || defined(BOOST_ASIO_HAS_SIGACTION) + + // Remove the registration from the registration table. + if (registrations_[reg->signal_number_] == reg) + registrations_[reg->signal_number_] = reg->next_in_table_; + if (reg->prev_in_table_) + reg->prev_in_table_->next_in_table_ = reg->next_in_table_; + if (reg->next_in_table_) + reg->next_in_table_->prev_in_table_ = reg->prev_in_table_; + + --state->registration_count_[reg->signal_number_]; + + impl.signals_ = reg->next_in_set_; + delete reg; + } + + ec = boost::system::error_code(); + return ec; +} + +boost::system::error_code signal_set_service::cancel( + signal_set_service::implementation_type& impl, + boost::system::error_code& ec) +{ + BOOST_ASIO_HANDLER_OPERATION(("signal_set", &impl, "cancel")); + + op_queue<operation> ops; + { + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + + while (signal_op* op = impl.queue_.front()) + { + op->ec_ = boost::asio::error::operation_aborted; + impl.queue_.pop(); + ops.push(op); + } + } + + io_service_.post_deferred_completions(ops); + + ec = boost::system::error_code(); + return ec; +} + +void signal_set_service::deliver_signal(int signal_number) +{ + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + + signal_set_service* service = state->service_list_; + while (service) + { + op_queue<operation> ops; + + registration* reg = service->registrations_[signal_number]; + while (reg) + { + if (reg->queue_->empty()) + { + ++reg->undelivered_; + } + else + { + while (signal_op* op = reg->queue_->front()) + { + op->signal_number_ = signal_number; + reg->queue_->pop(); + ops.push(op); + } + } + + reg = reg->next_in_table_; + } + + service->io_service_.post_deferred_completions(ops); + + service = service->next_; + } +} + +void signal_set_service::add_service(signal_set_service* service) +{ + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + +#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) + // If this is the first service to be created, open a new pipe. + if (state->service_list_ == 0) + open_descriptors(); +#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) + + // Insert service into linked list of all services. + service->next_ = state->service_list_; + service->prev_ = 0; + if (state->service_list_) + state->service_list_->prev_ = service; + state->service_list_ = service; + +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + // Register for pipe readiness notifications. + int read_descriptor = state->read_descriptor_; + lock.unlock(); + service->reactor_.register_internal_descriptor(reactor::read_op, + read_descriptor, service->reactor_data_, new pipe_read_op); +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +} + +void signal_set_service::remove_service(signal_set_service* service) +{ + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + + if (service->next_ || service->prev_ || state->service_list_ == service) + { +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + // Disable the pipe readiness notifications. + int read_descriptor = state->read_descriptor_; + lock.unlock(); + service->reactor_.deregister_descriptor( + read_descriptor, service->reactor_data_, false); + lock.lock(); +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) + + // Remove service from linked list of all services. + if (state->service_list_ == service) + state->service_list_ = service->next_; + if (service->prev_) + service->prev_->next_ = service->next_; + if (service->next_) + service->next_->prev_= service->prev_; + service->next_ = 0; + service->prev_ = 0; + +#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) + // If this is the last service to be removed, close the pipe. + if (state->service_list_ == 0) + close_descriptors(); +#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__) + } +} + +void signal_set_service::open_descriptors() +{ +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + signal_state* state = get_signal_state(); + + int pipe_fds[2]; + if (::pipe(pipe_fds) == 0) + { + state->read_descriptor_ = pipe_fds[0]; + ::fcntl(state->read_descriptor_, F_SETFL, O_NONBLOCK); + + state->write_descriptor_ = pipe_fds[1]; + ::fcntl(state->write_descriptor_, F_SETFL, O_NONBLOCK); + +#if defined(FD_CLOEXEC) + ::fcntl(state->read_descriptor_, F_SETFD, FD_CLOEXEC); + ::fcntl(state->write_descriptor_, F_SETFD, FD_CLOEXEC); +#endif // defined(FD_CLOEXEC) + } + else + { + boost::system::error_code ec(errno, + boost::asio::error::get_system_category()); + boost::asio::detail::throw_error(ec, "signal_set_service pipe"); + } +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +} + +void signal_set_service::close_descriptors() +{ +#if !defined(BOOST_ASIO_WINDOWS) \ + && !defined(BOOST_ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) + signal_state* state = get_signal_state(); + + if (state->read_descriptor_ != -1) + ::close(state->read_descriptor_); + state->read_descriptor_ = -1; + + if (state->write_descriptor_ != -1) + ::close(state->write_descriptor_); + state->write_descriptor_ = -1; +#endif // !defined(BOOST_ASIO_WINDOWS) + // && !defined(BOOST_ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +} + +void signal_set_service::start_wait_op( + signal_set_service::implementation_type& impl, signal_op* op) +{ + io_service_.work_started(); + + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + + registration* reg = impl.signals_; + while (reg) + { + if (reg->undelivered_ > 0) + { + --reg->undelivered_; + op->signal_number_ = reg->signal_number_; + io_service_.post_deferred_completion(op); + return; + } + + reg = reg->next_in_set_; + } + + impl.queue_.push(op); +} + +} // namespace detail +} // namespace asio +} // namespace boost + +#include <boost/asio/detail/pop_options.hpp> + +#endif // BOOST_ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP
diff --git a/boost/boost/asio/detail/impl/socket_ops.ipp b/boost/boost/asio/detail/impl/socket_ops.ipp new file mode 100644 index 0000000..dc068e0 --- /dev/null +++ b/boost/boost/asio/detail/impl/socket_ops.ipp
@@ -0,0 +1,3435 @@ +// +// detail/impl/socket_ops.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_IPP +#define BOOST_ASIO_DETAIL_SOCKET_OPS_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include <boost/asio/detail/config.hpp> + +#include <cctype> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <cerrno> +#include <new> +#include <boost/asio/detail/assert.hpp> +#include <boost/asio/detail/socket_ops.hpp> +#include <boost/asio/error.hpp> + +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) +# include <codecvt> +# include <locale> +# include <string> +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) \ + || defined(__MACH__) && defined(__APPLE__) +# if defined(BOOST_ASIO_HAS_PTHREADS) +# include <pthread.h> +# endif // defined(BOOST_ASIO_HAS_PTHREADS) +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // || defined(__MACH__) && defined(__APPLE__) + +#include <boost/asio/detail/push_options.hpp> + +namespace boost { +namespace asio { +namespace detail { +namespace socket_ops { + +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +struct msghdr { int msg_namelen; }; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + +#if defined(__hpux) +// HP-UX doesn't declare these functions extern "C", so they are declared again +// here to avoid linker errors about undefined symbols. +extern "C" char* if_indextoname(unsigned int, char*); +extern "C" unsigned int if_nametoindex(const char*); +#endif // defined(__hpux) + +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +inline void clear_last_error() +{ +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + WSASetLastError(0); +#else + errno = 0; +#endif +} + +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +template <typename ReturnType> +inline ReturnType error_wrapper(ReturnType return_value, + boost::system::error_code& ec) +{ +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ec = boost::system::error_code(WSAGetLastError(), + boost::asio::error::get_system_category()); +#else + ec = boost::system::error_code(errno, + boost::asio::error::get_system_category()); +#endif + return return_value; +} + +template <typename SockLenType> +inline socket_type call_accept(SockLenType msghdr::*, + socket_type s, socket_addr_type* addr, std::size_t* addrlen) +{ + SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0; + socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0); + if (addrlen) + *addrlen = (std::size_t)tmp_addrlen; + return result; +} + +socket_type accept(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return invalid_socket; + } + + clear_last_error(); + + socket_type new_s = error_wrapper(call_accept( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (new_s == invalid_socket) + return new_s; + +#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) + int optval = 1; + int result = error_wrapper(::setsockopt(new_s, + SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); + if (result != 0) + { + ::close(new_s); + return invalid_socket; + } +#endif + + ec = boost::system::error_code(); + return new_s; +} + +socket_type sync_accept(socket_type s, state_type state, + socket_addr_type* addr, std::size_t* addrlen, boost::system::error_code& ec) +{ + // Accept a socket. + for (;;) + { + // Try to complete the operation without blocking. + socket_type new_socket = socket_ops::accept(s, addr, addrlen, ec); + + // Check if operation succeeded. + if (new_socket != invalid_socket) + return new_socket; + + // Operation failed. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + { + if (state & user_set_non_blocking) + return invalid_socket; + // Fall through to retry operation. + } + else if (ec == boost::asio::error::connection_aborted) + { + if (state & enable_connection_aborted) + return invalid_socket; + // Fall through to retry operation. + } +#if defined(EPROTO) + else if (ec.value() == EPROTO) + { + if (state & enable_connection_aborted) + return invalid_socket; + // Fall through to retry operation. + } +#endif // defined(EPROTO) + else + return invalid_socket; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, ec) < 0) + return invalid_socket; + } +} + +#if defined(BOOST_ASIO_HAS_IOCP) + +void complete_iocp_accept(socket_type s, + void* output_buffer, DWORD address_length, + socket_addr_type* addr, std::size_t* addrlen, + socket_type new_socket, boost::system::error_code& ec) +{ + // Map non-portable errors to their portable counterparts. + if (ec.value() == ERROR_NETNAME_DELETED) + ec = boost::asio::error::connection_aborted; + + if (!ec) + { + // Get the address of the peer. + if (addr && addrlen) + { + LPSOCKADDR local_addr = 0; + int local_addr_length = 0; + LPSOCKADDR remote_addr = 0; + int remote_addr_length = 0; + GetAcceptExSockaddrs(output_buffer, 0, address_length, + address_length, &local_addr, &local_addr_length, + &remote_addr, &remote_addr_length); + if (static_cast<std::size_t>(remote_addr_length) > *addrlen) + { + ec = boost::asio::error::invalid_argument; + } + else + { + using namespace std; // For memcpy. + memcpy(addr, remote_addr, remote_addr_length); + *addrlen = static_cast<std::size_t>(remote_addr_length); + } + } + + // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname + // and getpeername will work on the accepted socket. + SOCKET update_ctx_param = s; + socket_ops::state_type state = 0; + socket_ops::setsockopt(new_socket, state, + SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, + &update_ctx_param, sizeof(SOCKET), ec); + } +} + +#else // defined(BOOST_ASIO_HAS_IOCP) + +bool non_blocking_accept(socket_type s, + state_type state, socket_addr_type* addr, std::size_t* addrlen, + boost::system::error_code& ec, socket_type& new_socket) +{ + for (;;) + { + // Accept the waiting connection. + new_socket = socket_ops::accept(s, addr, addrlen, ec); + + // Check if operation succeeded. + if (new_socket != invalid_socket) + return true; + + // Retry operation if interrupted by signal. + if (ec == boost::asio::error::interrupted) + continue; + + // Operation failed. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + { + if (state & user_set_non_blocking) + return true; + // Fall through to retry operation. + } + else if (ec == boost::asio::error::connection_aborted) + { + if (state & enable_connection_aborted) + return true; + // Fall through to retry operation. + } +#if defined(EPROTO) + else if (ec.value() == EPROTO) + { + if (state & enable_connection_aborted) + return true; + // Fall through to retry operation. + } +#endif // defined(EPROTO) + else + return true; + + return false; + } +} + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +template <typename SockLenType> +inline int call_bind(SockLenType msghdr::*, + socket_type s, const socket_addr_type* addr, std::size_t addrlen) +{ + return ::bind(s, addr, (SockLenType)addrlen); +} + +int bind(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(call_bind( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (result == 0) + ec = boost::system::error_code(); + return result; +} + +int close(socket_type s, state_type& state, + bool destruction, boost::system::error_code& ec) +{ + int result = 0; + if (s != invalid_socket) + { + // We don't want the destructor to block, so set the socket to linger in + // the background. If the user doesn't like this behaviour then they need + // to explicitly close the socket. + if (destruction && (state & user_set_linger)) + { + ::linger opt; + opt.l_onoff = 0; + opt.l_linger = 0; + boost::system::error_code ignored_ec; + socket_ops::setsockopt(s, state, SOL_SOCKET, + SO_LINGER, &opt, sizeof(opt), ignored_ec); + } + + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + result = error_wrapper(::closesocket(s), ec); +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + result = error_wrapper(::close(s), ec); +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + + if (result != 0 + && (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again)) + { + // According to UNIX Network Programming Vol. 1, it is possible for + // close() to fail with EWOULDBLOCK under certain circumstances. What + // isn't clear is the state of the descriptor after this error. The one + // current OS where this behaviour is seen, Windows, says that the socket + // remains open. Therefore we'll put the descriptor back into blocking + // mode and have another attempt at closing it. +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ioctl_arg_type arg = 0; + ::ioctlsocket(s, FIONBIO, &arg); +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +# if defined(__SYMBIAN32__) + int flags = ::fcntl(s, F_GETFL, 0); + if (flags >= 0) + ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK); +# else // defined(__SYMBIAN32__) + ioctl_arg_type arg = 0; + ::ioctl(s, FIONBIO, &arg); +# endif // defined(__SYMBIAN32__) +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + state &= ~non_blocking; + + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + result = error_wrapper(::closesocket(s), ec); +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + result = error_wrapper(::close(s), ec); +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + } + } + + if (result == 0) + ec = boost::system::error_code(); + return result; +} + +bool set_user_non_blocking(socket_type s, + state_type& state, bool value, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return false; + } + + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ioctl_arg_type arg = (value ? 1 : 0); + int result = error_wrapper(::ioctlsocket(s, FIONBIO, &arg), ec); +#elif defined(__SYMBIAN32__) + int result = error_wrapper(::fcntl(s, F_GETFL, 0), ec); + if (result >= 0) + { + clear_last_error(); + int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); + result = error_wrapper(::fcntl(s, F_SETFL, flag), ec); + } +#else + ioctl_arg_type arg = (value ? 1 : 0); + int result = error_wrapper(::ioctl(s, FIONBIO, &arg), ec); +#endif + + if (result >= 0) + { + ec = boost::system::error_code(); + if (value) + state |= user_set_non_blocking; + else + { + // Clearing the user-set non-blocking mode always overrides any + // internally-set non-blocking flag. Any subsequent asynchronous + // operations will need to re-enable non-blocking I/O. + state &= ~(user_set_non_blocking | internal_non_blocking); + } + return true; + } + + return false; +} + +bool set_internal_non_blocking(socket_type s, + state_type& state, bool value, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return false; + } + + if (!value && (state & user_set_non_blocking)) + { + // It does not make sense to clear the internal non-blocking flag if the + // user still wants non-blocking behaviour. Return an error and let the + // caller figure out whether to update the user-set non-blocking flag. + ec = boost::asio::error::invalid_argument; + return false; + } + + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + ioctl_arg_type arg = (value ? 1 : 0); + int result = error_wrapper(::ioctlsocket(s, FIONBIO, &arg), ec); +#elif defined(__SYMBIAN32__) + int result = error_wrapper(::fcntl(s, F_GETFL, 0), ec); + if (result >= 0) + { + clear_last_error(); + int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); + result = error_wrapper(::fcntl(s, F_SETFL, flag), ec); + } +#else + ioctl_arg_type arg = (value ? 1 : 0); + int result = error_wrapper(::ioctl(s, FIONBIO, &arg), ec); +#endif + + if (result >= 0) + { + ec = boost::system::error_code(); + if (value) + state |= internal_non_blocking; + else + state &= ~internal_non_blocking; + return true; + } + + return false; +} + +int shutdown(socket_type s, int what, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(::shutdown(s, what), ec); + if (result == 0) + ec = boost::system::error_code(); + return result; +} + +template <typename SockLenType> +inline int call_connect(SockLenType msghdr::*, + socket_type s, const socket_addr_type* addr, std::size_t addrlen) +{ + return ::connect(s, addr, (SockLenType)addrlen); +} + +int connect(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(call_connect( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (result == 0) + ec = boost::system::error_code(); +#if defined(__linux__) + else if (ec == boost::asio::error::try_again) + ec = boost::asio::error::no_buffer_space; +#endif // defined(__linux__) + return result; +} + +void sync_connect(socket_type s, const socket_addr_type* addr, + std::size_t addrlen, boost::system::error_code& ec) +{ + // Perform the connect operation. + socket_ops::connect(s, addr, addrlen, ec); + if (ec != boost::asio::error::in_progress + && ec != boost::asio::error::would_block) + { + // The connect operation finished immediately. + return; + } + + // Wait for socket to become ready. + if (socket_ops::poll_connect(s, ec) < 0) + return; + + // Get the error code from the connect operation. + int connect_error = 0; + size_t connect_error_len = sizeof(connect_error); + if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR, + &connect_error, &connect_error_len, ec) == socket_error_retval) + return; + + // Return the result of the connect operation. + ec = boost::system::error_code(connect_error, + boost::asio::error::get_system_category()); +} + +#if defined(BOOST_ASIO_HAS_IOCP) + +void complete_iocp_connect(socket_type s, boost::system::error_code& ec) +{ + // Map non-portable errors to their portable counterparts. + switch (ec.value()) + { + case ERROR_CONNECTION_REFUSED: + ec = boost::asio::error::connection_refused; + break; + case ERROR_NETWORK_UNREACHABLE: + ec = boost::asio::error::network_unreachable; + break; + case ERROR_HOST_UNREACHABLE: + ec = boost::asio::error::host_unreachable; + break; + case ERROR_SEM_TIMEOUT: + ec = boost::asio::error::timed_out; + break; + default: + break; + } + + if (!ec) + { + // Need to set the SO_UPDATE_CONNECT_CONTEXT option so that getsockname + // and getpeername will work on the connected socket. + socket_ops::state_type state = 0; + const int so_update_connect_context = 0x7010; + socket_ops::setsockopt(s, state, SOL_SOCKET, + so_update_connect_context, 0, 0, ec); + } +} + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +bool non_blocking_connect(socket_type s, boost::system::error_code& ec) +{ + // Check if the connect operation has finished. This is required since we may + // get spurious readiness notifications from the reactor. +#if defined(BOOST_ASIO_WINDOWS) \ + || defined(__CYGWIN__) \ + || defined(__SYMBIAN32__) + fd_set write_fds; + FD_ZERO(&write_fds); + FD_SET(s, &write_fds); + fd_set except_fds; + FD_ZERO(&except_fds); + FD_SET(s, &except_fds); + timeval zero_timeout; + zero_timeout.tv_sec = 0; + zero_timeout.tv_usec = 0; + int ready = ::select(s + 1, 0, &write_fds, &except_fds, &zero_timeout); +#else // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + pollfd fds; + fds.fd = s; + fds.events = POLLOUT; + fds.revents = 0; + int ready = ::poll(&fds, 1, 0); +#endif // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + if (ready == 0) + { + // The asynchronous connect operation is still in progress. + return false; + } + + // Get the error code from the connect operation. + int connect_error = 0; + size_t connect_error_len = sizeof(connect_error); + if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR, + &connect_error, &connect_error_len, ec) == 0) + { + if (connect_error) + { + ec = boost::system::error_code(connect_error, + boost::asio::error::get_system_category()); + } + else + ec = boost::system::error_code(); + } + + return true; +} + +int socketpair(int af, int type, int protocol, + socket_type sv[2], boost::system::error_code& ec) +{ +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + (void)(af); + (void)(type); + (void)(protocol); + (void)(sv); + ec = boost::asio::error::operation_not_supported; + return socket_error_retval; +#else + clear_last_error(); + int result = error_wrapper(::socketpair(af, type, protocol, sv), ec); + if (result == 0) + ec = boost::system::error_code(); + return result; +#endif +} + +bool sockatmark(socket_type s, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return false; + } + +#if defined(SIOCATMARK) + ioctl_arg_type value = 0; +# if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + int result = error_wrapper(::ioctlsocket(s, SIOCATMARK, &value), ec); +# else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + int result = error_wrapper(::ioctl(s, SIOCATMARK, &value), ec); +# endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + if (result == 0) + ec = boost::system::error_code(); +# if defined(ENOTTY) + if (ec.value() == ENOTTY) + ec = boost::asio::error::not_socket; +# endif // defined(ENOTTY) +#else // defined(SIOCATMARK) + int value = error_wrapper(::sockatmark(s), ec); + if (value != -1) + ec = boost::system::error_code(); +#endif // defined(SIOCATMARK) + + return ec ? false : value != 0; +} + +size_t available(socket_type s, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + ioctl_arg_type value = 0; +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + int result = error_wrapper(::ioctlsocket(s, FIONREAD, &value), ec); +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + int result = error_wrapper(::ioctl(s, FIONREAD, &value), ec); +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + if (result == 0) + ec = boost::system::error_code(); +#if defined(ENOTTY) + if (ec.value() == ENOTTY) + ec = boost::asio::error::not_socket; +#endif // defined(ENOTTY) + + return ec ? static_cast<size_t>(0) : static_cast<size_t>(value); +} + +int listen(socket_type s, int backlog, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(::listen(s, backlog), ec); + if (result == 0) + ec = boost::system::error_code(); + return result; +} + +inline void init_buf_iov_base(void*& base, void* addr) +{ + base = addr; +} + +template <typename T> +inline void init_buf_iov_base(T& base, void* addr) +{ + base = static_cast<T>(addr); +} + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +typedef WSABUF buf; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +typedef iovec buf; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + +void init_buf(buf& b, void* data, size_t size) +{ +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + b.buf = static_cast<char*>(data); + b.len = static_cast<u_long>(size); +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + init_buf_iov_base(b.iov_base, data); + b.iov_len = size; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +void init_buf(buf& b, const void* data, size_t size) +{ +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + b.buf = static_cast<char*>(const_cast<void*>(data)); + b.len = static_cast<u_long>(size); +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + init_buf_iov_base(b.iov_base, const_cast<void*>(data)); + b.iov_len = size; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr) +{ + name = addr; +} + +inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr) +{ + name = const_cast<socket_addr_type*>(addr); +} + +template <typename T> +inline void init_msghdr_msg_name(T& name, socket_addr_type* addr) +{ + name = reinterpret_cast<T>(addr); +} + +template <typename T> +inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr) +{ + name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr)); +} + +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_ASIO_WINDOWS) || defined(__CYGWIN__) + // Receive some data. + DWORD recv_buf_count = static_cast<DWORD>(count); + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int result = error_wrapper(::WSARecv(s, bufs, + recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec); + if (ec.value() == ERROR_NETNAME_DELETED) + ec = boost::asio::error::connection_reset; + else if (ec.value() == ERROR_PORT_UNREACHABLE) + ec = boost::asio::error::connection_refused; + if (result != 0) + return socket_error_retval; + ec = boost::system::error_code(); + return bytes_transferred; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + msg.msg_iov = bufs; + 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; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +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) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // A request to read 0 bytes on a stream is a no-op. + if (all_empty && (state & stream_oriented)) + { + ec = boost::system::error_code(); + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Check for EOF. + if ((state & stream_oriented) && bytes == 0) + { + ec = boost::asio::error::eof; + return 0; + } + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, ec) < 0) + return 0; + } +} + +#if defined(BOOST_ASIO_HAS_IOCP) + +void complete_iocp_recv(state_type state, + const weak_cancel_token_type& cancel_token, bool all_empty, + boost::system::error_code& ec, size_t bytes_transferred) +{ + // Map non-portable errors to their portable counterparts. + if (ec.value() == ERROR_NETNAME_DELETED) + { + if (cancel_token.expired()) + ec = boost::asio::error::operation_aborted; + else + ec = boost::asio::error::connection_reset; + } + else if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } + + // Check for connection closed. + else if (!ec && bytes_transferred == 0 + && (state & stream_oriented) != 0 + && !all_empty) + { + ec = boost::asio::error::eof; + } +} + +#else // defined(BOOST_ASIO_HAS_IOCP) + +bool non_blocking_recv(socket_type s, + buf* bufs, size_t count, int flags, bool is_stream, + boost::system::error_code& ec, size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec); + + // Check for end of stream. + if (is_stream && bytes == 0) + { + ec = boost::asio::error::eof; + return true; + } + + // Retry operation if interrupted by signal. + if (ec == boost::asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +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(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // Receive some data. + DWORD recv_buf_count = static_cast<DWORD>(count); + DWORD bytes_transferred = 0; + DWORD recv_flags = flags; + int tmp_addrlen = (int)*addrlen; + int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count, + &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec); + *addrlen = (std::size_t)tmp_addrlen; + if (ec.value() == ERROR_NETNAME_DELETED) + ec = boost::asio::error::connection_reset; + else if (ec.value() == ERROR_PORT_UNREACHABLE) + ec = boost::asio::error::connection_refused; + if (result != 0) + return socket_error_retval; + ec = boost::system::error_code(); + return bytes_transferred; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + init_msghdr_msg_name(msg.msg_name, addr); + msg.msg_namelen = static_cast<int>(*addrlen); + msg.msg_iov = bufs; + 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(); + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, + size_t count, int flags, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::recvfrom( + s, bufs, count, flags, addr, addrlen, ec); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, ec) < 0) + return 0; + } +} + +#if defined(BOOST_ASIO_HAS_IOCP) + +void complete_iocp_recvfrom( + const weak_cancel_token_type& cancel_token, + boost::system::error_code& ec) +{ + // Map non-portable errors to their portable counterparts. + if (ec.value() == ERROR_NETNAME_DELETED) + { + if (cancel_token.expired()) + ec = boost::asio::error::operation_aborted; + else + ec = boost::asio::error::connection_reset; + } + else if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } +} + +#else // defined(BOOST_ASIO_HAS_IOCP) + +bool non_blocking_recvfrom(socket_type s, + buf* bufs, size_t count, int flags, + socket_addr_type* addr, std::size_t* addrlen, + boost::system::error_code& ec, size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + 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) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +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(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + out_flags = 0; + return socket_ops::recv(s, bufs, count, in_flags, ec); +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + msg.msg_iov = bufs; + 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(); + out_flags = msg.msg_flags; + } + else + out_flags = 0; + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +size_t sync_recvmsg(socket_type s, state_type state, + buf* bufs, size_t count, int in_flags, int& out_flags, + boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::recvmsg( + s, bufs, count, in_flags, out_flags, ec); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_read(s, 0, ec) < 0) + return 0; + } +} + +#if defined(BOOST_ASIO_HAS_IOCP) + +void complete_iocp_recvmsg( + const weak_cancel_token_type& cancel_token, + boost::system::error_code& ec) +{ + // Map non-portable errors to their portable counterparts. + if (ec.value() == ERROR_NETNAME_DELETED) + { + if (cancel_token.expired()) + ec = boost::asio::error::operation_aborted; + else + ec = boost::asio::error::connection_reset; + } + else if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } +} + +#else // defined(BOOST_ASIO_HAS_IOCP) + +bool non_blocking_recvmsg(socket_type s, + buf* bufs, size_t count, int in_flags, int& out_flags, + boost::system::error_code& ec, size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + 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) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +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_ASIO_WINDOWS) || defined(__CYGWIN__) + // Send the data. + DWORD send_buf_count = static_cast<DWORD>(count); + DWORD bytes_transferred = 0; + DWORD send_flags = flags; + int result = error_wrapper(::WSASend(s, const_cast<buf*>(bufs), + send_buf_count, &bytes_transferred, send_flags, 0, 0), ec); + if (ec.value() == ERROR_NETNAME_DELETED) + ec = boost::asio::error::connection_reset; + else if (ec.value() == ERROR_PORT_UNREACHABLE) + ec = boost::asio::error::connection_refused; + if (result != 0) + return socket_error_retval; + ec = boost::system::error_code(); + return bytes_transferred; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + msg.msg_iov = const_cast<buf*>(bufs); + msg.msg_iovlen = static_cast<int>(count); +#if defined(__linux__) + flags |= MSG_NOSIGNAL; +#endif // defined(__linux__) + signed_size_type result = error_wrapper(::sendmsg(s, &msg, flags), ec); + if (result >= 0) + ec = boost::system::error_code(); + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +size_t sync_send(socket_type s, state_type state, const buf* bufs, + size_t count, int flags, bool all_empty, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // A request to write 0 bytes to a stream is a no-op. + if (all_empty && (state & stream_oriented)) + { + ec = boost::system::error_code(); + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_write(s, 0, ec) < 0) + return 0; + } +} + +#if defined(BOOST_ASIO_HAS_IOCP) + +void complete_iocp_send( + const weak_cancel_token_type& cancel_token, + boost::system::error_code& ec) +{ + // Map non-portable errors to their portable counterparts. + if (ec.value() == ERROR_NETNAME_DELETED) + { + if (cancel_token.expired()) + ec = boost::asio::error::operation_aborted; + else + ec = boost::asio::error::connection_reset; + } + else if (ec.value() == ERROR_PORT_UNREACHABLE) + { + ec = boost::asio::error::connection_refused; + } +} + +#else // defined(BOOST_ASIO_HAS_IOCP) + +bool non_blocking_send(socket_type s, + const buf* bufs, size_t count, int flags, + boost::system::error_code& ec, size_t& bytes_transferred) +{ + for (;;) + { + // Write some data. + signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec); + + // Retry operation if interrupted by signal. + if (ec == boost::asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +#endif // defined(BOOST_ASIO_HAS_IOCP) + +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(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + // Send the data. + DWORD send_buf_count = static_cast<DWORD>(count); + DWORD bytes_transferred = 0; + int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs), + send_buf_count, &bytes_transferred, flags, addr, + static_cast<int>(addrlen), 0, 0), ec); + if (ec.value() == ERROR_NETNAME_DELETED) + ec = boost::asio::error::connection_reset; + else if (ec.value() == ERROR_PORT_UNREACHABLE) + ec = boost::asio::error::connection_refused; + if (result != 0) + return socket_error_retval; + ec = boost::system::error_code(); + return bytes_transferred; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + msghdr msg = msghdr(); + init_msghdr_msg_name(msg.msg_name, addr); + msg.msg_namelen = static_cast<int>(addrlen); + msg.msg_iov = const_cast<buf*>(bufs); + msg.msg_iovlen = static_cast<int>(count); +#if defined(__linux__) + flags |= MSG_NOSIGNAL; +#endif // defined(__linux__) + signed_size_type result = error_wrapper(::sendmsg(s, &msg, flags), ec); + if (result >= 0) + ec = boost::system::error_code(); + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +size_t sync_sendto(socket_type s, state_type state, const buf* bufs, + size_t count, int flags, const socket_addr_type* addr, + std::size_t addrlen, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return 0; + } + + // Write some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = socket_ops::sendto( + s, bufs, count, flags, addr, addrlen, ec); + + // Check if operation succeeded. + if (bytes >= 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != boost::asio::error::would_block + && ec != boost::asio::error::try_again)) + return 0; + + // Wait for socket to become ready. + if (socket_ops::poll_write(s, 0, ec) < 0) + return 0; + } +} + +#if !defined(BOOST_ASIO_HAS_IOCP) + +bool non_blocking_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, size_t& bytes_transferred) +{ + for (;;) + { + // Write some data. + 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) + continue; + + // Check if we need to run the operation again. + if (ec == boost::asio::error::would_block + || ec == boost::asio::error::try_again) + return false; + + // Operation is complete. + if (bytes >= 0) + { + ec = boost::system::error_code(); + bytes_transferred = bytes; + } + else + bytes_transferred = 0; + + return true; + } +} + +#endif // !defined(BOOST_ASIO_HAS_IOCP) + +socket_type socket(int af, int type, int protocol, + boost::system::error_code& ec) +{ + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + socket_type s = error_wrapper(::WSASocketW(af, type, protocol, 0, 0, + WSA_FLAG_OVERLAPPED), ec); + if (s == invalid_socket) + return s; + + if (af == BOOST_ASIO_OS_DEF(AF_INET6)) + { + // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to + // false. This will only succeed on Windows Vista and later versions of + // Windows, where a dual-stack IPv4/v6 implementation is available. + DWORD optval = 0; + ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + reinterpret_cast<const char*>(&optval), sizeof(optval)); + } + + ec = boost::system::error_code(); + + return s; +#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) + socket_type s = error_wrapper(::socket(af, type, protocol), ec); + if (s == invalid_socket) + return s; + + int optval = 1; + int result = error_wrapper(::setsockopt(s, + SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); + if (result != 0) + { + ::close(s); + return invalid_socket; + } + + return s; +#else + int s = error_wrapper(::socket(af, type, protocol), ec); + if (s >= 0) + ec = boost::system::error_code(); + return s; +#endif +} + +template <typename SockLenType> +inline int call_setsockopt(SockLenType msghdr::*, + socket_type s, int level, int optname, + const void* optval, std::size_t optlen) +{ + return ::setsockopt(s, level, optname, + (const char*)optval, (SockLenType)optlen); +} + +int setsockopt(socket_type s, state_type& state, int level, int optname, + const void* optval, std::size_t optlen, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + + if (level == custom_socket_option_level && optname == always_fail_option) + { + ec = boost::asio::error::invalid_argument; + return socket_error_retval; + } + + if (level == custom_socket_option_level + && optname == enable_connection_aborted_option) + { + if (optlen != sizeof(int)) + { + ec = boost::asio::error::invalid_argument; + return socket_error_retval; + } + + if (*static_cast<const int*>(optval)) + state |= enable_connection_aborted; + else + state &= ~enable_connection_aborted; + ec = boost::system::error_code(); + return 0; + } + + if (level == SOL_SOCKET && optname == SO_LINGER) + state |= user_set_linger; + +#if defined(__BORLANDC__) + // Mysteriously, using the getsockopt and setsockopt functions directly with + // Borland C++ results in incorrect values being set and read. The bug can be + // worked around by using function addresses resolved with GetProcAddress. + if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) + { + typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int); + if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt")) + { + clear_last_error(); + return error_wrapper(sso(s, level, optname, + reinterpret_cast<const char*>(optval), + static_cast<int>(optlen)), ec); + } + } + ec = boost::asio::error::fault; + return socket_error_retval; +#else // defined(__BORLANDC__) + clear_last_error(); + int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen, + s, level, optname, optval, optlen), ec); + if (result == 0) + { + ec = boost::system::error_code(); + +#if defined(__MACH__) && defined(__APPLE__) \ + || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + // To implement portable behaviour for SO_REUSEADDR with UDP sockets we + // need to also set SO_REUSEPORT on BSD-based platforms. + if ((state & datagram_oriented) + && level == SOL_SOCKET && optname == SO_REUSEADDR) + { + call_setsockopt(&msghdr::msg_namelen, s, + SOL_SOCKET, SO_REUSEPORT, optval, optlen); + } +#endif + } + + return result; +#endif // defined(__BORLANDC__) +} + +template <typename SockLenType> +inline int call_getsockopt(SockLenType msghdr::*, + socket_type s, int level, int optname, + void* optval, std::size_t* optlen) +{ + SockLenType tmp_optlen = (SockLenType)*optlen; + int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen); + *optlen = (std::size_t)tmp_optlen; + return result; +} + +int getsockopt(socket_type s, state_type state, int level, int optname, + void* optval, size_t* optlen, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + + if (level == custom_socket_option_level && optname == always_fail_option) + { + ec = boost::asio::error::invalid_argument; + return socket_error_retval; + } + + if (level == custom_socket_option_level + && optname == enable_connection_aborted_option) + { + if (*optlen != sizeof(int)) + { + ec = boost::asio::error::invalid_argument; + return socket_error_retval; + } + + *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0; + ec = boost::system::error_code(); + return 0; + } + +#if defined(__BORLANDC__) + // Mysteriously, using the getsockopt and setsockopt functions directly with + // Borland C++ results in incorrect values being set and read. The bug can be + // worked around by using function addresses resolved with GetProcAddress. + if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) + { + typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*); + if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt")) + { + clear_last_error(); + int tmp_optlen = static_cast<int>(*optlen); + int result = error_wrapper(gso(s, level, optname, + reinterpret_cast<char*>(optval), &tmp_optlen), ec); + *optlen = static_cast<size_t>(tmp_optlen); + if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY + && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) + { + // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are + // only supported on Windows Vista and later. To simplify program logic + // we will fake success of getting this option and specify that the + // value is non-zero (i.e. true). This corresponds to the behavior of + // IPv6 sockets on Windows platforms pre-Vista. + *static_cast<DWORD*>(optval) = 1; + ec = boost::system::error_code(); + } + return result; + } + } + ec = boost::asio::error::fault; + return socket_error_retval; +#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + clear_last_error(); + int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen, + s, level, optname, optval, optlen), ec); + if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY + && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) + { + // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only + // supported on Windows Vista and later. To simplify program logic we will + // fake success of getting this option and specify that the value is + // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets + // on Windows platforms pre-Vista. + *static_cast<DWORD*>(optval) = 1; + ec = boost::system::error_code(); + } + if (result == 0) + ec = boost::system::error_code(); + return result; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + clear_last_error(); + int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen, + s, level, optname, optval, optlen), ec); +#if defined(__linux__) + if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int) + && (optname == SO_SNDBUF || optname == SO_RCVBUF)) + { + // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel + // to set the buffer size to N*2. Linux puts additional stuff into the + // buffers so that only about half is actually available to the application. + // The retrieved value is divided by 2 here to make it appear as though the + // correct value has been set. + *static_cast<int*>(optval) /= 2; + } +#endif // defined(__linux__) + if (result == 0) + ec = boost::system::error_code(); + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +template <typename SockLenType> +inline int call_getpeername(SockLenType msghdr::*, + socket_type s, socket_addr_type* addr, std::size_t* addrlen) +{ + SockLenType tmp_addrlen = (SockLenType)*addrlen; + int result = ::getpeername(s, addr, &tmp_addrlen); + *addrlen = (std::size_t)tmp_addrlen; + return result; +} + +int getpeername(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, bool cached, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + if (cached) + { + // Check if socket is still connected. + DWORD connect_time = 0; + size_t connect_time_len = sizeof(connect_time); + if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_CONNECT_TIME, + &connect_time, &connect_time_len, ec) == socket_error_retval) + { + return socket_error_retval; + } + if (connect_time == 0xFFFFFFFF) + { + ec = boost::asio::error::not_connected; + return socket_error_retval; + } + + // The cached value is still valid. + ec = boost::system::error_code(); + return 0; + } +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + (void)cached; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + + clear_last_error(); + int result = error_wrapper(call_getpeername( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (result == 0) + ec = boost::system::error_code(); + return result; +} + +template <typename SockLenType> +inline int call_getsockname(SockLenType msghdr::*, + socket_type s, socket_addr_type* addr, std::size_t* addrlen) +{ + SockLenType tmp_addrlen = (SockLenType)*addrlen; + int result = ::getsockname(s, addr, &tmp_addrlen); + *addrlen = (std::size_t)tmp_addrlen; + return result; +} + +int getsockname(socket_type s, socket_addr_type* addr, + std::size_t* addrlen, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); + int result = error_wrapper(call_getsockname( + &msghdr::msg_namelen, s, addr, addrlen), ec); + if (result == 0) + ec = boost::system::error_code(); + return result; +} + +int ioctl(socket_type s, state_type& state, int cmd, + ioctl_arg_type* arg, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec); +#elif defined(__MACH__) && defined(__APPLE__) \ + || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) + int result = error_wrapper(::ioctl(s, + static_cast<unsigned int>(cmd), arg), ec); +#else + int result = error_wrapper(::ioctl(s, cmd, arg), ec); +#endif + if (result >= 0) + { + ec = boost::system::error_code(); + + // When updating the non-blocking mode we always perform the ioctl syscall, + // even if the flags would otherwise indicate that the socket is already in + // the correct state. This ensures that the underlying socket is put into + // the state that has been requested by the user. If the ioctl syscall was + // successful then we need to update the flags to match. + if (cmd == static_cast<int>(FIONBIO)) + { + if (*arg) + { + state |= user_set_non_blocking; + } + else + { + // Clearing the non-blocking mode always overrides any internally-set + // non-blocking flag. Any subsequent asynchronous operations will need + // to re-enable non-blocking I/O. + state &= ~(user_set_non_blocking | internal_non_blocking); + } + } + } + + return result; +} + +int select(int nfds, fd_set* readfds, fd_set* writefds, + fd_set* exceptfds, timeval* timeout, boost::system::error_code& ec) +{ + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + if (!readfds && !writefds && !exceptfds && timeout) + { + DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; + if (milliseconds == 0) + milliseconds = 1; // Force context switch. + ::Sleep(milliseconds); + ec = boost::system::error_code(); + return 0; + } + + // The select() call allows timeout values measured in microseconds, but the + // system clock (as wrapped by boost::posix_time::microsec_clock) typically + // has a resolution of 10 milliseconds. This can lead to a spinning select + // reactor, meaning increased CPU usage, when waiting for the earliest + // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight + // spin we'll use a minimum timeout of 1 millisecond. + if (timeout && timeout->tv_sec == 0 + && timeout->tv_usec > 0 && timeout->tv_usec < 1000) + timeout->tv_usec = 1000; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + +#if defined(__hpux) && defined(__SELECT) + timespec ts; + ts.tv_sec = timeout ? timeout->tv_sec : 0; + ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0; + return error_wrapper(::pselect(nfds, readfds, + writefds, exceptfds, timeout ? &ts : 0, 0), ec); +#else + int result = error_wrapper(::select(nfds, readfds, + writefds, exceptfds, timeout), ec); + if (result >= 0) + ec = boost::system::error_code(); + return result; +#endif +} + +int poll_read(socket_type s, state_type state, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + +#if defined(BOOST_ASIO_WINDOWS) \ + || defined(__CYGWIN__) \ + || defined(__SYMBIAN32__) + fd_set fds; + FD_ZERO(&fds); + FD_SET(s, &fds); + timeval zero_timeout; + zero_timeout.tv_sec = 0; + zero_timeout.tv_usec = 0; + timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0; + clear_last_error(); + int result = error_wrapper(::select(s + 1, &fds, 0, 0, timeout), ec); +#else // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + pollfd fds; + fds.fd = s; + fds.events = POLLIN; + fds.revents = 0; + int timeout = (state & user_set_non_blocking) ? 0 : -1; + clear_last_error(); + int result = error_wrapper(::poll(&fds, 1, timeout), ec); +#endif // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + if (result == 0) + ec = (state & user_set_non_blocking) + ? boost::asio::error::would_block : boost::system::error_code(); + else if (result > 0) + ec = boost::system::error_code(); + return result; +} + +int poll_write(socket_type s, state_type state, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + +#if defined(BOOST_ASIO_WINDOWS) \ + || defined(__CYGWIN__) \ + || defined(__SYMBIAN32__) + fd_set fds; + FD_ZERO(&fds); + FD_SET(s, &fds); + timeval zero_timeout; + zero_timeout.tv_sec = 0; + zero_timeout.tv_usec = 0; + timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0; + clear_last_error(); + int result = error_wrapper(::select(s + 1, 0, &fds, 0, timeout), ec); +#else // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + pollfd fds; + fds.fd = s; + fds.events = POLLOUT; + fds.revents = 0; + int timeout = (state & user_set_non_blocking) ? 0 : -1; + clear_last_error(); + int result = error_wrapper(::poll(&fds, 1, timeout), ec); +#endif // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + if (result == 0) + ec = (state & user_set_non_blocking) + ? boost::asio::error::would_block : boost::system::error_code(); + else if (result > 0) + ec = boost::system::error_code(); + return result; +} + +int poll_connect(socket_type s, boost::system::error_code& ec) +{ + if (s == invalid_socket) + { + ec = boost::asio::error::bad_descriptor; + return socket_error_retval; + } + +#if defined(BOOST_ASIO_WINDOWS) \ + || defined(__CYGWIN__) \ + || defined(__SYMBIAN32__) + fd_set write_fds; + FD_ZERO(&write_fds); + FD_SET(s, &write_fds); + fd_set except_fds; + FD_ZERO(&except_fds); + FD_SET(s, &except_fds); + clear_last_error(); + int result = error_wrapper(::select( + s + 1, 0, &write_fds, &except_fds, 0), ec); + if (result >= 0) + ec = boost::system::error_code(); + return result; +#else // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) + pollfd fds; + fds.fd = s; + fds.events = POLLOUT; + fds.revents = 0; + clear_last_error(); + int result = error_wrapper(::poll(&fds, 1, -1), ec); + if (result >= 0) + ec = boost::system::error_code(); + return result; +#endif // defined(BOOST_ASIO_WINDOWS) + // || defined(__CYGWIN__) + // || defined(__SYMBIAN32__) +} + +#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +const char* inet_ntop(int af, const void* src, char* dest, size_t length, + unsigned long scope_id, boost::system::error_code& ec) +{ + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + using namespace std; // For sprintf. + const unsigned char* bytes = static_cast<const unsigned char*>(src); + if (af == BOOST_ASIO_OS_DEF(AF_INET)) + { + sprintf_s(dest, length, "%u.%u.%u.%u", + bytes[0], bytes[1], bytes[2], bytes[3]); + return dest; + } + else if (af == BOOST_ASIO_OS_DEF(AF_INET6)) + { + size_t n = 0, b = 0, z = 0; + while (n < length && b < 16) + { + if (bytes[b] == 0 && bytes[b + 1] == 0 && z == 0) + { + do b += 2; while (b < 16 && bytes[b] == 0 && bytes[b + 1] == 0); + n += sprintf_s(dest + n, length - n, ":%s", b < 16 ? "" : ":"), ++z; + } + else + { + n += sprintf_s(dest + n, length - n, "%s%x", b ? ":" : "", + (static_cast<u_long_type>(bytes[b]) << 8) | bytes[b + 1]); + b += 2; + } + } + if (scope_id) + n += sprintf_s(dest + n, length - n, "%%%lu", scope_id); + return dest; + } + else + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } +#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + using namespace std; // For memcpy. + + if (af != BOOST_ASIO_OS_DEF(AF_INET) && af != BOOST_ASIO_OS_DEF(AF_INET6)) + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } + + union + { + socket_addr_type base; + sockaddr_storage_type storage; + sockaddr_in4_type v4; + sockaddr_in6_type v6; + } address; + DWORD address_length; + if (af == BOOST_ASIO_OS_DEF(AF_INET)) + { + address_length = sizeof(sockaddr_in4_type); + address.v4.sin_family = BOOST_ASIO_OS_DEF(AF_INET); + address.v4.sin_port = 0; + memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type)); + } + else // AF_INET6 + { + address_length = sizeof(sockaddr_in6_type); + address.v6.sin6_family = BOOST_ASIO_OS_DEF(AF_INET6); + address.v6.sin6_port = 0; + address.v6.sin6_flowinfo = 0; + address.v6.sin6_scope_id = scope_id; + memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type)); + } + + DWORD string_length = static_cast<DWORD>(length); +#if defined(BOOST_NO_ANSI_APIS) || (defined(_MSC_VER) && (_MSC_VER >= 1800)) + LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR)); + int result = error_wrapper(::WSAAddressToStringW(&address.base, + address_length, 0, string_buffer, &string_length), ec); + ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, + dest, static_cast<int>(length), 0, 0); +#else + int result = error_wrapper(::WSAAddressToStringA( + &address.base, address_length, 0, dest, &string_length), ec); +#endif + + // Windows may set error code on success. + if (result != socket_error_retval) + ec = boost::system::error_code(); + + // Windows may not set an error code on failure. + else if (result == socket_error_retval && !ec) + ec = boost::asio::error::invalid_argument; + + return result == socket_error_retval ? 0 : dest; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + 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 == BOOST_ASIO_OS_DEF(AF_INET6) && scope_id != 0) + { + using namespace std; // For strcat and sprintf. + char if_name[IF_NAMESIZE + 1] = "%"; + const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src); + bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe) + && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80)); + bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff) + && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02)); + if ((!is_link_local && !is_multicast_link_local) + || if_indextoname(static_cast<unsigned>(scope_id), if_name + 1) == 0) + sprintf(if_name + 1, "%lu", scope_id); + strcat(dest, if_name); + } + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +int inet_pton(int af, const char* src, void* dest, + unsigned long* scope_id, boost::system::error_code& ec) +{ + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + using namespace std; // For sscanf. + unsigned char* bytes = static_cast<unsigned char*>(dest); + if (af == BOOST_ASIO_OS_DEF(AF_INET)) + { + unsigned int b0, b1, b2, b3; + if (sscanf_s(src, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) != 4) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + if (b0 > 255 || b1 > 255 || b2 > 255 || b3 > 255) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + bytes[0] = static_cast<unsigned char>(b0); + bytes[1] = static_cast<unsigned char>(b1); + bytes[2] = static_cast<unsigned char>(b2); + bytes[3] = static_cast<unsigned char>(b3); + ec = boost::system::error_code(); + return 1; + } + else if (af == BOOST_ASIO_OS_DEF(AF_INET6)) + { + unsigned char* bytes = static_cast<unsigned char*>(dest); + std::memset(bytes, 0, 16); + unsigned char back_bytes[16] = { 0 }; + int num_front_bytes = 0, num_back_bytes = 0; + const char* p = src; + + enum { fword, fcolon, bword, scope, done } state = fword; + unsigned long current_word = 0; + while (state != done) + { + if (current_word > 0xFFFF) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + + switch (state) + { + case fword: + if (*p >= '0' && *p <= '9') + current_word = current_word * 16 + *p++ - '0'; + else if (*p >= 'a' && *p <= 'f') + current_word = current_word * 16 + *p++ - 'a' + 10; + else if (*p >= 'A' && *p <= 'F') + current_word = current_word * 16 + *p++ - 'A' + 10; + else + { + if (num_front_bytes == 16) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + + bytes[num_front_bytes++] = (current_word >> 8) & 0xFF; + bytes[num_front_bytes++] = current_word & 0xFF; + current_word = 0; + + if (*p == ':') + state = fcolon, ++p; + else if (*p == '%') + state = scope, ++p; + else if (*p == 0) + state = done; + else + { + ec = boost::asio::error::invalid_argument; + return -1; + } + } + break; + + case fcolon: + if (*p == ':') + state = bword, ++p; + else + state = fword; + break; + + case bword: + if (*p >= '0' && *p <= '9') + current_word = current_word * 16 + *p++ - '0'; + else if (*p >= 'a' && *p <= 'f') + current_word = current_word * 16 + *p++ - 'a' + 10; + else if (*p >= 'A' && *p <= 'F') + current_word = current_word * 16 + *p++ - 'A' + 10; + else + { + if (num_front_bytes + num_back_bytes == 16) + { + ec = boost::asio::error::invalid_argument; + return -1; + } + + back_bytes[num_back_bytes++] = (current_word >> 8) & 0xFF; + back_bytes[num_back_bytes++] = current_word & 0xFF; + current_word = 0; + + if (*p == ':') + state = bword, ++p; + else if (*p == '%') + state = scope, ++p; + else if (*p == 0) + state = done; + else + { + ec = boost::asio::error::invalid_argument; + return -1; + } + } + break; + + case scope: + if (*p >= '0' && *p <= '9') + current_word = current_word * 10 + *p++ - '0'; + else if (*p == 0) + *scope_id = current_word, state = done; + else + { + ec = boost::asio::error::invalid_argument; + return -1; + } + break; + + default: + break; + } + } + + for (int i = 0; i < num_back_bytes; ++i) + bytes[16 - num_back_bytes + i] = back_bytes[i]; + + ec = boost::system::error_code(); + return 1; + } + else + { + ec = boost::asio::error::address_family_not_supported; + return -1; + } +#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + using namespace std; // For memcpy and strcmp. + + if (af != BOOST_ASIO_OS_DEF(AF_INET) && af != BOOST_ASIO_OS_DEF(AF_INET6)) + { + ec = boost::asio::error::address_family_not_supported; + return -1; + } + + union + { + socket_addr_type base; + sockaddr_storage_type storage; + sockaddr_in4_type v4; + sockaddr_in6_type v6; + } address; + int address_length = sizeof(sockaddr_storage_type); +#if defined(BOOST_NO_ANSI_APIS) || (defined(_MSC_VER) && (_MSC_VER >= 1800)) + int num_wide_chars = static_cast<int>(strlen(src)) + 1; + LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR)); + ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars); + int result = error_wrapper(::WSAStringToAddressW( + wide_buffer, af, 0, &address.base, &address_length), ec); +#else + int result = error_wrapper(::WSAStringToAddressA( + const_cast<char*>(src), af, 0, &address.base, &address_length), ec); +#endif + + if (af == BOOST_ASIO_OS_DEF(AF_INET)) + { + if (result != socket_error_retval) + { + memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type)); + ec = boost::system::error_code(); + } + else if (strcmp(src, "255.255.255.255") == 0) + { + static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE; + ec = boost::system::error_code(); + } + } + else // AF_INET6 + { + if (result != socket_error_retval) + { + memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type)); + if (scope_id) + *scope_id = address.v6.sin6_scope_id; + ec = boost::system::error_code(); + } + } + + // Windows may not set an error code on failure. + if (result == socket_error_retval && !ec) + ec = boost::asio::error::invalid_argument; + + if (result != socket_error_retval) + ec = boost::system::error_code(); + + return result == socket_error_retval ? -1 : 1; +#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + using namespace std; // For strchr, memcpy and atoi. + + // On some platforms, inet_pton fails if an address string contains a scope + // id. Detect and remove the scope id before passing the string to inet_pton. + const bool is_v6 = (af == BOOST_ASIO_OS_DEF(AF_INET6)); + const char* if_name = is_v6 ? strchr(src, '%') : 0; + char src_buf[max_addr_v6_str_len + 1]; + const char* src_ptr = src; + if (if_name != 0) + { + if (if_name - src > max_addr_v6_str_len) + { + ec = boost::asio::error::invalid_argument; + return 0; + } + memcpy(src_buf, src, if_name - src); + src_buf[if_name - src] = 0; + src_ptr = src_buf; + } + + int result = error_wrapper(::inet_pton(af, src_ptr, dest), ec); + if (result <= 0 && !ec) + ec = boost::asio::error::invalid_argument; + if (result > 0 && is_v6 && scope_id) + { + using namespace std; // For strchr and atoi. + *scope_id = 0; + if (if_name != 0) + { + in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest); + bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe) + && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80)); + bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff) + && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02)); + if (is_link_local || is_multicast_link_local) + *scope_id = if_nametoindex(if_name + 1); + if (*scope_id == 0) + *scope_id = atoi(if_name + 1); + } + } + return result; +#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) +} + +int gethostname(char* name, int namelen, boost::system::error_code& ec) +{ + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS_RUNTIME) + try + { + using namespace Windows::Foundation::Collections; + using namespace Windows::Networking; + using namespace Windows::Networking::Connectivity; + IVectorView<HostName^>^ hostnames = NetworkInformation::GetHostNames(); + for (unsigned i = 0; i < hostnames->Size; ++i) + { + HostName^ hostname = hostnames->GetAt(i); + if (hostname->Type == HostNameType::DomainName) + { + std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; + std::string raw_name = converter.to_bytes(hostname->RawName->Data()); + if (namelen > 0 && raw_name.size() < static_cast<std::size_t>(namelen)) + { + strcpy_s(name, namelen, raw_name.c_str()); + return 0; + } + } + } + return -1; + } + catch (Platform::Exception^ e) + { + ec = boost::system::error_code(e->HResult, + boost::system::system_category()); + return -1; + } +#else // defined(BOOST_ASIO_WINDOWS_RUNTIME) + int result = error_wrapper(::gethostname(name, namelen), ec); +# if defined(BOOST_ASIO_WINDOWS) + if (result == 0) + ec = boost::system::error_code(); +# endif // defined(BOOST_ASIO_WINDOWS) + return result; +#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) +} + +#if !defined(BOOST_ASIO_WINDOWS_RUNTIME) + +#if !defined(BOOST_ASIO_HAS_GETADDRINFO) + +// The following functions are only needed for emulation of getaddrinfo and +// getnameinfo. + +inline boost::system::error_code translate_netdb_error(int error) +{ + switch (error) + { + case 0: + return boost::system::error_code(); + case HOST_NOT_FOUND: + return boost::asio::error::host_not_found; + case TRY_AGAIN: + return boost::asio::error::host_not_found_try_again; + case NO_RECOVERY: + return boost::asio::error::no_recovery; + case NO_DATA: + return boost::asio::error::no_data; + default: + BOOST_ASIO_ASSERT(false); + return boost::asio::error::invalid_argument; + } +} + +inline hostent* gethostbyaddr(const char* addr, int length, int af, + hostent* result, char* buffer, int buflength, boost::system::error_code& ec) +{ + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + (void)(buffer); + (void)(buflength); + hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec); + if (!retval) + return 0; + ec = boost::system::error_code(); + *result = *retval; + return retval; +#elif defined(__sun) || defined(__QNX__) + int error = 0; + hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result, + buffer, buflength, &error), ec); + if (error) + ec = translate_netdb_error(error); + return retval; +#elif defined(__MACH__) && defined(__APPLE__) + (void)(buffer); + (void)(buflength); + int error = 0; + hostent* retval = error_wrapper(::getipnodebyaddr( + addr, length, af, &error), ec); + if (error) + ec = translate_netdb_error(error); + if (!retval) + return 0; + *result = *retval; + return retval; +#else + hostent* retval = 0; + int error = 0; + error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer, + buflength, &retval, &error), ec); + if (error) + ec = translate_netdb_error(error); + return retval; +#endif +} + +inline hostent* gethostbyname(const char* name, int af, struct hostent* result, + char* buffer, int buflength, int ai_flags, boost::system::error_code& ec) +{ + clear_last_error(); +#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__) + (void)(buffer); + (void)(buflength); + (void)(ai_flags); + if (af != BOOST_ASIO_OS_DEF(AF_INET)) + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } + hostent* retval = error_wrapper(::gethostbyname(name), ec); + if (!retval) + return 0; + ec = boost::system::error_code(); + *result = *retval; + return result; +#elif defined(__sun) || defined(__QNX__) + (void)(ai_flags); + if (af != BOOST_ASIO_OS_DEF(AF_INET)) + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } + int error = 0; + hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer, + buflength, &error), ec); + if (error) + ec = translate_netdb_error(error); + return retval; +#elif defined(__MACH__) && defined(__APPLE__) + (void)(buffer); + (void)(buflength); + int error = 0; + hostent* retval = error_wrapper(::getipnodebyname( + name, af, ai_flags, &error), ec); + if (error) + ec = translate_netdb_error(error); + if (!retval) + return 0; + *result = *retval; + return retval; +#else + (void)(ai_flags); + if (af != BOOST_ASIO_OS_DEF(AF_INET)) + { + ec = boost::asio::error::address_family_not_supported; + return 0; + } + hostent* retval = 0; + int error = 0; + error_wrapper(::gethostbyname_r(name, result, + buffer, buflength, &retval, &error), ec); + if (error) + ec = translate_netdb_error(error); + return retval; +#endif +} + +inline void freehostent(hostent* h) +{ +#if defined(__MACH__) && defined(__APPLE__) + if (h) + ::freehostent(h); +#else + (void)(h); +#endif +} + +// Emulation of getaddrinfo based on implementation in: +// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998. + +struct gai_search +{ + const char* host; + int family; +}; + +inline int gai_nsearch(const char* host, + const addrinfo_type* hints, gai_search (&search)[2]) +{ + int search_count = 0; + if (host == 0 || host[0] == '\0') + { + if (hints->ai_flags & AI_PASSIVE) + { + // No host and AI_PASSIVE implies wildcard bind. + switch (hints->ai_family) + { + case BOOST_ASIO_OS_DEF(AF_INET): + search[search_count].host = "0.0.0.0"; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); + ++search_count; + break; + case BOOST_ASIO_OS_DEF(AF_INET6): + search[search_count].host = "0::0"; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); + ++search_count; + break; + case BOOST_ASIO_OS_DEF(AF_UNSPEC): + search[search_count].host = "0::0"; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); + ++search_count; + search[search_count].host = "0.0.0.0"; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); + ++search_count; + break; + default: + break; + } + } + else + { + // No host and not AI_PASSIVE means connect to local host. + switch (hints->ai_family) + { + case BOOST_ASIO_OS_DEF(AF_INET): + search[search_count].host = "localhost"; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); + ++search_count; + break; + case BOOST_ASIO_OS_DEF(AF_INET6): + search[search_count].host = "localhost"; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); + ++search_count; + break; + case BOOST_ASIO_OS_DEF(AF_UNSPEC): + search[search_count].host = "localhost"; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); + ++search_count; + search[search_count].host = "localhost"; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); + ++search_count; + break; + default: + break; + } + } + } + else + { + // Host is specified. + switch (hints->ai_family) + { + case BOOST_ASIO_OS_DEF(AF_INET): + search[search_count].host = host; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); + ++search_count; + break; + case BOOST_ASIO_OS_DEF(AF_INET6): + search[search_count].host = host; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); + ++search_count; + break; + case BOOST_ASIO_OS_DEF(AF_UNSPEC): + search[search_count].host = host; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET6); + ++search_count; + search[search_count].host = host; + search[search_count].family = BOOST_ASIO_OS_DEF(AF_INET); + ++search_count; + break; + default: + break; + } + } + return search_count; +} + +template <typename T> +inline T* gai_alloc(std::size_t size = sizeof(T)) +{ + using namespace std; + T* p = static_cast<T*>(::operator new(size, std::nothrow)); + if (p) + memset(p, 0, size); + return p; +} + +inline void gai_free(void* p) +{ + ::operator delete(p); +} + +inline void gai_strcpy(char* target, const char* source, std::size_t max_size) +{ + using namespace std; +#if defined(BOOST_ASIO_HAS_SECURE_RTL) + strcpy_s(target, max_size, source); +#else // defined(BOOST_ASIO_HAS_SECURE_RTL) + *target = 0; + strncat(target, source, max_size); +#endif // defined(BOOST_ASIO_HAS_SECURE_RTL) +} + +enum { gai_clone_flag = 1 << 30 }; + +inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints, + const void* addr, int family) +{ + using namespace std; + + addrinfo_type* ai = gai_alloc<addrinfo_type>(); + if (ai == 0) + return EAI_MEMORY; + + ai->ai_next = 0; + **next = ai; + *next = &ai->ai_next; + + ai->ai_canonname = 0; + ai->ai_socktype = hints->ai_socktype; + if (ai->ai_socktype == 0) + ai->ai_flags |= gai_clone_flag; + ai->ai_protocol = hints->ai_protocol; + ai->ai_family = family; + + switch (ai->ai_family) + { + case BOOST_ASIO_OS_DEF(AF_INET): + { + sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>(); + if (sinptr == 0) + return EAI_MEMORY; + sinptr->sin_family = BOOST_ASIO_OS_DEF(AF_INET); + memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type)); + ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr); + ai->ai_addrlen = sizeof(sockaddr_in4_type); + break; + } + case BOOST_ASIO_OS_DEF(AF_INET6): + { + sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>(); + if (sin6ptr == 0) + return EAI_MEMORY; + sin6ptr->sin6_family = BOOST_ASIO_OS_DEF(AF_INET6); + memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type)); + ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr); + ai->ai_addrlen = sizeof(sockaddr_in6_type); + break; + } + default: + break; + } + + return 0; +} + +inline addrinfo_type* gai_clone(addrinfo_type* ai) +{ + using namespace std; + + addrinfo_type* new_ai = gai_alloc<addrinfo_type>(); + if (new_ai == 0) + return new_ai; + + new_ai->ai_next = ai->ai_next; + ai->ai_next = new_ai; + + new_ai->ai_flags = 0; + new_ai->ai_family = ai->ai_family; + new_ai->ai_socktype = ai->ai_socktype; + new_ai->ai_protocol = ai->ai_protocol; + new_ai->ai_canonname = 0; + new_ai->ai_addrlen = ai->ai_addrlen; + new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen); + memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen); + + return new_ai; +} + +inline int gai_port(addrinfo_type* aihead, int port, int socktype) +{ + int num_found = 0; + + for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next) + { + if (ai->ai_flags & gai_clone_flag) + { + if (ai->ai_socktype != 0) + { + ai = gai_clone(ai); + if (ai == 0) + return -1; + // ai now points to newly cloned entry. + } + } + else if (ai->ai_socktype != socktype) + { + // Ignore if mismatch on socket type. + continue; + } + + ai->ai_socktype = socktype; + + switch (ai->ai_family) + { + case BOOST_ASIO_OS_DEF(AF_INET): + { + sockaddr_in4_type* sinptr = + reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr); + sinptr->sin_port = port; + ++num_found; + break; + } + case BOOST_ASIO_OS_DEF(AF_INET6): + { + sockaddr_in6_type* sin6ptr = + reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr); + sin6ptr->sin6_port = port; + ++num_found; + break; + } + default: + break; + } + } + + return num_found; +} + +inline int gai_serv(addrinfo_type* aihead, + const addrinfo_type* hints, const char* serv) +{ + using namespace std; + + int num_found = 0; + + if ( +#if defined(AI_NUMERICSERV) + (hints->ai_flags & AI_NUMERICSERV) || +#endif + isdigit(static_cast<unsigned char>(serv[0]))) + { + int port = htons(atoi(serv)); + if (hints->ai_socktype) + { + // Caller specifies socket type. + int rc = gai_port(aihead, port, hints->ai_socktype); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + } + else + { + // Caller does not specify socket type. + int rc = gai_port(aihead, port, SOCK_STREAM); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + rc = gai_port(aihead, port, SOCK_DGRAM); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + } + } + else + { + // Try service name with TCP first, then UDP. + if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM) + { + servent* sptr = getservbyname(serv, "tcp"); + if (sptr != 0) + { + int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + } + } + if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM) + { + servent* sptr = getservbyname(serv, "udp"); + if (sptr != 0) + { + int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM); + if (rc < 0) + return EAI_MEMORY; + num_found += rc; + } + } + } + + if (num_found == 0) + { + if (hints->ai_socktype == 0) + { + // All calls to getservbyname() failed. + return EAI_NONAME; + } + else + { + // Service not supported for socket type. + return EAI_SERVICE; + } + } + + return 0; +} + +inline int gai_echeck(const char* host, const char* service, + int flags, int family, int socktype, int protocol) +{ + (void)(flags); + (void)(protocol); + + // Host or service must be specified. + if (host == 0 || host[0] == '\0') + if (service == 0 || service[0] == '\0') + return EAI_NONAME; + + // Check combination of family and socket type. + switch (family) + { + case BOOST_ASIO_OS_DEF(AF_UNSPEC): + break; + case BOOST_ASIO_OS_DEF(AF_INET): + case BOOST_ASIO_OS_DEF(AF_INET6): + if (service != 0 && service[0] != '\0') + if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM) + return EAI_SOCKTYPE; + break; + default: + return EAI_FAMILY; + } + + return 0; +} + +inline void freeaddrinfo_emulation(addrinfo_type* aihead) +{ + addrinfo_type* ai = aihead; + while (ai) + { + gai_free(ai->ai_addr); + gai_free(ai->ai_canonname); + addrinfo_type* ainext = ai->ai_next; + gai_free(ai); + ai = ainext; + } +} + +inline int getaddrinfo_emulation(const char* host, const char* service, + const addrinfo_type* hintsp, addrinfo_type** result) +{ + // Set up linked list of addrinfo structures. + addrinfo_type* aihead = 0; + addrinfo_type** ainext = &aihead; + char* canon = 0; + + // Supply default hints if not specified by caller. + addrinfo_type hints = addrinfo_type(); + hints.ai_family = BOOST_ASIO_OS_DEF(AF_UNSPEC); + if (hintsp) + hints = *hintsp; + + // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED + // and AI_ALL flags. +#if defined(AI_V4MAPPED) + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET6)) + hints.ai_flags &= ~AI_V4MAPPED; +#endif +#if defined(AI_ALL) + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET6)) + hints.ai_flags &= ~AI_ALL; +#endif + + // Basic error checking. + int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family, + hints.ai_socktype, hints.ai_protocol); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + return rc; + } + + gai_search search[2]; + int search_count = gai_nsearch(host, &hints, search); + for (gai_search* sptr = search; sptr < search + search_count; ++sptr) + { + // Check for IPv4 dotted decimal string. + in4_addr_type inaddr; + boost::system::error_code ec; + if (socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET), + sptr->host, &inaddr, 0, ec) == 1) + { + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_UNSPEC) + && hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET)) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + return EAI_FAMILY; + } + if (sptr->family == BOOST_ASIO_OS_DEF(AF_INET)) + { + rc = gai_aistruct(&ainext, &hints, &inaddr, BOOST_ASIO_OS_DEF(AF_INET)); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + return rc; + } + } + continue; + } + + // Check for IPv6 hex string. + in6_addr_type in6addr; + if (socket_ops::inet_pton(BOOST_ASIO_OS_DEF(AF_INET6), + sptr->host, &in6addr, 0, ec) == 1) + { + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_UNSPEC) + && hints.ai_family != BOOST_ASIO_OS_DEF(AF_INET6)) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + return EAI_FAMILY; + } + if (sptr->family == BOOST_ASIO_OS_DEF(AF_INET6)) + { + rc = gai_aistruct(&ainext, &hints, &in6addr, + BOOST_ASIO_OS_DEF(AF_INET6)); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + return rc; + } + } + continue; + } + + // Look up hostname. + hostent hent; + char hbuf[8192] = ""; + hostent* hptr = socket_ops::gethostbyname(sptr->host, + sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec); + if (hptr == 0) + { + if (search_count == 2) + { + // Failure is OK if there are multiple searches. + continue; + } + freeaddrinfo_emulation(aihead); + gai_free(canon); + if (ec == boost::asio::error::host_not_found) + return EAI_NONAME; + if (ec == boost::asio::error::host_not_found_try_again) + return EAI_AGAIN; + if (ec == boost::asio::error::no_recovery) + return EAI_FAIL; + if (ec == boost::asio::error::no_data) + return EAI_NONAME; + return EAI_NONAME; + } + + // Check for address family mismatch if one was specified. + if (hints.ai_family != BOOST_ASIO_OS_DEF(AF_UNSPEC) + && hints.ai_family != hptr->h_addrtype) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + socket_ops::freehostent(hptr); + return EAI_FAMILY; + } + + // Save canonical name first time. + if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0] + && (hints.ai_flags & AI_CANONNAME) && canon == 0) + { + std::size_t canon_len = strlen(hptr->h_name) + 1; + canon = gai_alloc<char>(canon_len); + if (canon == 0) + { + freeaddrinfo_emulation(aihead); + socket_ops::freehostent(hptr); + return EAI_MEMORY; + } + gai_strcpy(canon, hptr->h_name, canon_len); + } + + // Create an addrinfo structure for each returned address. + for (char** ap = hptr->h_addr_list; *ap; ++ap) + { + rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + gai_free(canon); + socket_ops::freehostent(hptr); + return EAI_FAMILY; + } + } + + socket_ops::freehostent(hptr); + } + + // Check if we found anything. + if (aihead == 0) + { + gai_free(canon); + return EAI_NONAME; + } + + // Return canonical name in first entry. + if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME)) + { + if (canon) + { + aihead->ai_canonname = canon; + canon = 0; + } + else + { + std::size_t canonname_len = strlen(search[0].host) + 1; + aihead->ai_canonname = gai_alloc<char>(canonname_len); + if (aihead->ai_canonname == 0) + { + freeaddrinfo_emulation(aihead); + return EAI_MEMORY; + } + gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len); + } + } + gai_free(canon); + + // Process the service name. + if (service != 0 && service[0] != '\0') + { + rc = gai_serv(aihead, &hints, service); + if (rc != 0) + { + freeaddrinfo_emulation(aihead); + return rc; + } + } + + // Return result to caller. + *result = aihead; + return 0; +} + +inline boost::system::error_code getnameinfo_emulation( + const socket_addr_type* sa, std::size_t salen, char* host, + std::size_t hostlen, char* serv, std::size_t servlen, int flags, + boost::system::error_code& ec) +{ + using namespace std; + + const char* addr; + size_t addr_len; + unsigned short port; + switch (sa->sa_family) + { + case BOOST_ASIO_OS_DEF(AF_INET): + if (salen != sizeof(sockaddr_in4_type)) + { + return ec = boost::asio::error::invalid_argument; + } + addr = reinterpret_cast<const char*>( + &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr); + addr_len = sizeof(in4_addr_type); + port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port; + break; + case BOOST_ASIO_OS_DEF(AF_INET6): + if (salen != sizeof(sockaddr_in6_type)) + { + return ec = boost::asio::error::invalid_argument; + } + addr = reinterpret_cast<const char*>( + &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr); + addr_len = sizeof(in6_addr_type); + port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port; + break; + default: + return ec = boost::asio::error::address_family_not_supported; + } + + if (host && hostlen > 0) + { + if (flags & NI_NUMERICHOST) + { + if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0) + { + return ec; + } + } + else + { + hostent hent; + char hbuf[8192] = ""; + hostent* hptr = socket_ops::gethostbyaddr(addr, + static_cast<int>(addr_len), sa->sa_family, + &hent, hbuf, sizeof(hbuf), ec); + if (hptr && hptr->h_name && hptr->h_name[0] != '\0') + { + if (flags & NI_NOFQDN) + { + char* dot = strchr(hptr->h_name, '.'); + if (dot) + { + *dot = 0;